I get an error if I increase the number of data (e.g. NUM_DATA = 120)
Yes, I can confirm. After some debugging I found that this is due to accessing the data array beyond its highest element. Please modify the OnCalculate event as follows:
{ Event handler which returns the z value of each data point lying at (AX,AY)
in the plane }
procedure TForm1.Chart1ColorMapSeries1Calculate(const AX, AY: Double; out
AZ: Double);
var
indexX, indexY: Integer;
begin
// Lookup data in matrix
// The shift by 0.5 is for centering the color boxes around the ticks.
// Make sure that we do not go beyond the highest index.
indexX := Min(NUM_DATA-1, trunc(AX+0.5));
indexY := Min(NUM_DATA-1, trunc(AY+0.5));
AZ := DataValues[indexX, indexY];
end;
This modification returns valid data if, due to rounding errors, the series requests a z value beyond the data array limits.
Maybe the 0.5 offset requires some more explanation:
TColorMapSeries is a "function" series, this means that it gets its data from a function calculated for every point in the x/y plane. This is what the OnCalculate event does: It gets the coordinates of the data point for which a function value z is needed and calculates the function value.
In your case, the x values are the indexes in the 2-dimensional DataValues array. But the TColorMapSeries does not need z values only at integers, but also at any value in between. Mathematically speaking, it requires a "step function". Therefore I chop off all decimals from the x/y coordinates, and this is the array index, as simple as that. In this way the colormap series gets that tiled look. But without anything else the axis tick marks would be located at the lower left edge of each tile. Typically they should be in the center of each tile. Therefore, I am adding 0.5 (= half a tile) to the x/y coordinates. In this way the first tile extends between -0.5 and +0.5: the x coordinate of the very left point is -0.5, in the vent handler we add 0.5 to get 0.0, i.e. the data index is 0. This is true also for all points before they reach 0.5. Therefore the x data range of the series starts at -0.5. The same with y. And the last data point, after shifting by -0.5, is at NUM_DATA-0.5. These values are to be assigned to the Extent of the series.
Your question 1 on the ColorSource: The ColorMapSeries has a built-in color interpolation procedure (ColorByValue()). It needs pivots defined by the ColorSource. Each pivot is defined by a value-color pair. Because interpolation has to be made for both axes a value has to be provided for x and y (first and second parameter fo the Add method of the ColorSource):
ColorSource.Add(value, value, '', color_of_value);
Suppose you want a two-color gradient: the data minimum corresponds to the firstcolor, the maximum to the last color. Intermediate colors are calculated by the series using linear interpolation of the rgb components. If you want a three-color gradient you have to assign a third color to an intermediate data value. In the demo I used the value which is at 0.3 of the distance between max and Min, closer to the min. If I had selected 0.5 the point would be exactly in the middle. 0.7 would be closer to the max value.