How to plot contours for a sparse data set?

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Geocentrix
Newbie
Newbie
Posts: 8
Joined: Thu Sep 30, 2021 12:00 am

How to plot contours for a sparse data set?

Post by Geocentrix » Fri Jun 06, 2025 9:36 am

I am using the TContourPlot to show some data for which I have only 55 data points (data is inclued at the end of this post). On the plot below, I additionally draw small grey circles where my data points are located (i.e on a triangular pattern).
PileGroup.jpg
PileGroup.jpg (39.77 KiB) Viewed 803 times
The plot I am expecting to get is as follows:
Expected contours.jpg
Expected contours.jpg (50.12 KiB) Viewed 803 times
(I created this in Excel but had to interpolate between the data points, adding an extra point between every four circles)

However, I cannot get TChart to produce any contours for this data set.

Are there any settings within TChart that I can use to produce contours for this set?

Any suggestions would be most welcome!

Andrew

The data I have is as follows:

Code: Select all

Index	X	Y	Z
0	-8	192.4	0
1	8	192.4	0
2	2	195.3	-7
3	2	195.3	7
4	-2	195.3	-7
5	-2	195.3	7
6	-5	197.7	5.25
7	5	197.7	-5.25
8	5	197.7	5.25
9	-5	197.7	-5.25
10	7	200.4	1.75
11	-7	200.4	1.75
12	-7	200.4	-1.75
13	7	200.4	-1.75
14	-6	202.2	-3.5
15	6	202.2	-3.5
16	6	202.2	3.5
17	-6	202.2	3.5
18	-3	209.4	-5.25
19	3	209.4	5.25
20	-3	209.4	5.25
21	3	209.4	-5.25
22	-6	213.1	0
23	6	213.1	0
24	1	215	5.25
25	1	215	-5.25
26	-1	215	5.25
27	-1	215	-5.25
28	4	217.5	-3.5
29	4	217.5	3.5
30	-4	217.5	-3.5
31	-4	217.5	3.5
32	5	218.7	1.75
33	-5	218.7	-1.75
34	-5	218.7	1.75
35	5	218.7	-1.75
36	2	226.5	3.5
37	-2	226.5	-3.5
38	2	226.5	-3.5
39	-2	226.5	3.5
40	4	228.2	0
41	-4	228.2	0
42	0	229.4	3.5
43	0	229.4	-3.5
44	3	230.8	-1.75
45	-3	230.8	-1.75
46	3	230.8	1.75
47	-3	230.8	1.75
48	-1	236.8	1.75
49	1	236.8	1.75
50	1	236.8	-1.75
51	-1	236.8	-1.75
52	2	237.3	0
53	-2	237.3	0
54	0	240.3	0

The data used to produce the plot on Excel is:

Code: Select all

x	y	z
-8	189.6	0
-7	197.5	-1.75
-7	198.65	0
-7	197.5	1.75
-6	199.2	-3.5
-6	205.55	-1.75
-6	210	0
-6	205.55	1.75
-6	199.2	3.5
-5	194.8	-5.25
-5	205.95	-3.5
-5	215.5	-1.75
-5	216.475	0
-5	215.5	1.75
-5	205.95	3.5
-5	194.8	5.25
-4	205.1333333	-5.25
-4	214.3	-3.5
-4	220.525	-1.75
-4	224.9	0
-4	220.525	1.75
-4	214.3	3.5
-4	205.1333333	5.25
-3	206.3	-5.25
-3	217.8	-3.5
-3	227.4	-1.75
-3	228.375	0
-3	227.4	1.75
-3	217.8	3.5
-3	206.3	5.25
-2	192.4	-7
-2	208.45	-5.25
-2	223.2	-3.5
-2	229.45	-1.75
-2	233.8	0
-2	229.45	1.75
-2	223.2	3.5
-2	208.45	5.25
-2	192.4	7
-1	211.9	-5.25
-1	223.625	-3.5
-1	233.4	-1.75
-1	234.35	0
-1	233.4	1.75
-1	223.625	3.5
-1	211.9	5.25
0	216.6	-5.25
0	226	-3.5
0	232.4	-1.75
0	236.8	0
0	232.4	1.75
0	226	3.5
0	216.6	5.25
1	211.9	-5.25
1	223.625	-3.5
1	233.4	-1.75
1	234.35	0
1	233.4	1.75
1	223.625	3.5
1	211.9	5.25
2	192.4	-7
2	208.45	-5.25
2	223.2	-3.5
2	229.45	-1.75
2	233.8	0
2	229.45	1.75
2	223.2	3.5
2	208.45	5.25
2	192.4	7
3	206.3	-5.25
3	217.8	-3.5
3	227.4	-1.75
3	228.375	0
3	227.4	1.75
3	217.8	3.5
3	206.3	5.25
4	205.1333333	-5.25
4	214.3	-3.5
4	220.525	-1.75
4	224.9	0
4	220.525	1.75
4	214.3	3.5
4	205.1333333	5.25
5	194.8	-5.25
5	205.95	-3.5
5	215.5	-1.75
5	216.475	0
5	215.5	1.75
5	205.95	3.5
5	194.8	5.25
6	199.2	-3.5
6	205.55	-1.75
6	210	0
6	205.55	1.75
6	199.2	3.5
7	197.5	-1.75
7	198.65	0
7	197.5	1.75
8	189.6	0

Yeray
Site Admin
Site Admin
Posts: 9691
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to plot contours for a sparse data set?

Post by Yeray » Thu Jun 12, 2025 12:49 pm

Hello,

I've been playing with your data and I came up with this:
contour.png
contour.png (54.29 KiB) Viewed 282 times
I'm not sure if that fits your requirements.
Note the PopulateMissingPoints method helps to make sure the data follows a regular grid structure so the TContourSeries can handle it.
Note there's also a TPointSeries with the raw data I used for testing.

Code: Select all

uses System.Math.Vectors, System.Generics.Collections, System.Generics.Defaults, System.Math,
  Chart, TeEngine, TeeSurfa, Series;

var Chart1: TChart;

function PopulateMissingPoints(const AList: TList<TPoint3D>): TList<TPoint3D>;
var
  XValues, YValues: TList<Double>;
  XYDict: TDictionary<string, Boolean>;
  Point: TPoint3D;
  X, Y: Double;
  Key: string;
begin
  // Initialize collections
  XValues := TList<Double>.Create;
  YValues := TList<Double>.Create;
  XYDict := TDictionary<string, Boolean>.Create;
  Result := TList<TPoint3D>.Create;

  try
    // Collect unique X and Y values
    for Point in AList do
    begin
      if not XValues.Contains(Point.X) then
        XValues.Add(Point.X);
      if not YValues.Contains(Point.Y) then
        YValues.Add(Point.Y);

      // Populate dictionary for existence checks
      Key := Format('%.5f,%.5f', [Point.X, Point.Y]);
      XYDict.AddOrSetValue(Key, True);
    end;

    // Sort coordinates to maintain grid structure
    XValues.Sort;
    YValues.Sort;

    // Generate all possible X-Y combinations
    for X in XValues do
      for Y in YValues do
      begin
        Key := Format('%.5f,%.5f', [X, Y]);
        if not XYDict.ContainsKey(Key) then
          Result.Add(TPoint3D.Create(X, Y, 0));
      end;

    // Add original points and sort the combined list
    Result.AddRange(AList);
    Result.Sort(TComparer<TPoint3D>.Construct(
      function(const A, B: TPoint3D): Integer
      begin
        Result := CompareValue(A.Y, B.Y);
        if Result = 0 then
          Result := CompareValue(A.X, B.X);
      end
    ));
  finally
    XValues.Free;
    YValues.Free;
    XYDict.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var MyPoint   : TPointSeries;
    MyContour : TContourSeries;

    tmpLines   : TStrings;
    tmpFields  : TStrings;
    n          : Integer;
    xx, yy, zz : Double;

    data: TList<TPoint3D>;
const AFileName='D:\Downloads\contour_data.csv';
begin
  FormatSettings.DecimalSeparator:='.';

  Chart1:=TChart.Create(Self);

  with Chart1 do
  begin
    Parent:=Self;
    Align:=alClient;
    Color:=clWhite;
    Gradient.Visible:=False;
    Walls.Hide;
    Legend.Hide;
    View3D:=False;
    Axes.Left.Grid.Hide;
    Axes.Bottom.Grid.Hide;
    Axes.Left.SetMinMax(-8, 8);
    Axes.Bottom.SetMinMax(-18, 18);
    Axes.Bottom.Increment:=2;
  end;

  MyPoint:=TPointSeries(Chart1.AddSeries(TPointSeries));
  MyPoint.Pointer.Size:=2;
  MyPoint.Pointer.Style:=psCircle;
  MyPoint.BeginUpdate;

  MyContour:=TContourSeries(Chart1.AddSeries(TContourSeries));
  with MyContour do
  begin
    IrregularGrid:=True;
    //Filled:=True;
    BeginUpdate;
  end;

  data:=TList<TPoint3D>.Create;
  tmpLines:=TStringList.Create;
  tmpLines.LoadFromFile(AFileName);

  n:=1;
  while n<tmpLines.Count do
  begin
    tmpFields:=TStringList.Create;
    tmpFields.Delimiter:=';';
    tmpFields.DelimitedText:=tmpLines[n];

    xx := StrToFloat(tmpFields[1]);
    zz := StrToFloat(tmpFields[2]);
    yy := StrToFloat(tmpFields[3]);

    data.Add(Point3D(xx, yy, zz));

    Inc(n);
  end;

  for var i:=0 to data.Count-1 do
    MyPoint.AddXY(data[i].X, data[i].Y);

  data:=PopulateMissingPoints(data);

  for var i:=0 to data.Count-1 do
    MyContour.AddXYZ(data[i].X, data[i].Z, data[i].Y);

  MyPoint.EndUpdate;
  MyContour.EndUpdate;

  MyPoint.Visible:=False;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply