3D Scatter Plots

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
CAC
Newbie
Newbie
Posts: 44
Joined: Tue Jun 20, 2006 12:00 am
Location: Plain City, Ohio
Contact:

3D Scatter Plots

Post by CAC » Wed Dec 20, 2006 1:48 am

Is it possible to construct a scatter plot in which the points are located in 3-dimensional space, and have a certain depth?

I would like to be able to plot concentration data associated with soil samples (located by x,y) from specfic depth intervals (z-z') and then color code by concentration.

Thanks

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Wed Dec 20, 2006 7:04 am

Hi.

Try using TPoint3DSeries. It more less does exactly what you need (gives you control over individual point z=z(x,y) coordinate).
Marjan Slatinek,
http://www.steema.com

CAC
Newbie
Newbie
Posts: 44
Joined: Tue Jun 20, 2006 12:00 am
Location: Plain City, Ohio
Contact:

Post by CAC » Wed Dec 20, 2006 1:46 pm

Thanks....I also looked briefly at the TTeeCanvas3D.Cylinder

Cylinder(Vertical: Boolean; Left, Top, Right, Bottom, Z0, Z1: Integer; Dark3D: Boolean); override;

I'm guessing that the cylinder will work perfectly in my situation. I would also guess that if I set vertical to true, then Left and Right will be my X and Y; Z0 and Z1 would size my cylinder and set it in 3D space, but I am a little confused about Top and Bottom.

Any guidance would be appreciated.
Thanks
Craig

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Thu Dec 21, 2006 11:58 am

Hi.

Hmm... I don't think this drawing method will mimic true 3d scatter plot.

The Cylinder canvas method will draw a vertical or horizontal cylinder using Left,Right,Top,Bottom as bounds in x-y (2d projection) plane and Z0 and Z1 as bounds in z plane. That is, the Z0 and Z1 (if not equal) define the "depth", Left, Right define left and right bounds of the cylinder (x coordinates) and Bottom, Top define bottom and top bounds (y coordinates) of cylinder.
Marjan Slatinek,
http://www.steema.com

CAC
Newbie
Newbie
Posts: 44
Joined: Tue Jun 20, 2006 12:00 am
Location: Plain City, Ohio
Contact:

Post by CAC » Thu Dec 21, 2006 1:18 pm

Would "TCanvas3D.ZLine3D" work? I was thinking if I made the line heavy enough it may mimic a cylinder in 3D space, and a round point in 2D.

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Fri Dec 22, 2006 9:16 am

Hi.

It should give you similar, but not the same look. The same could be achieved using MoveTo3D and LineTo3D methods.

To get a true 3d feel and look I'd stick with Cylinder method. Using it it'd be a lot easier to control the z coordinate (concentration). For example, the following code will draw a cylinder at specific z=z(x,y) coordinate:

Code: Select all

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var z0,z1: Integer;
    xc,yc: Integer;
    x,y,concentration: double;
begin
  With Chart1.Canvas, Chart1 do
  begin
    x := 2.2;
    y := 3.3;
    concentration := 1.5;
    xc := Axes.Bottom.CalcXPosValue(x);
    yc := Axes.Left.CalcYPosValue(y);
    z0 := Axes.Depth.CalcPosValue(0.0);
    z1 := Axes.Depth.CalcPosValue(1.5);
    Cylinder(true,xc-3,yc-3,xc+3,yc+3,z0,z1,false);
  end;
end;
IMHO, similarly you could also use the Cube method to describe concentration=concentration(x,y) relation:

Code: Select all

    Cube(xc-3,xc+3,yc-3,yc+3,z0,z1,false);
Marjan Slatinek,
http://www.steema.com

CAC
Newbie
Newbie
Posts: 44
Joined: Tue Jun 20, 2006 12:00 am
Location: Plain City, Ohio
Contact:

Post by CAC » Fri Dec 22, 2006 12:56 pm

Marjan,

Thanks so much for all your help.

Craig

CAC
Newbie
Newbie
Posts: 44
Joined: Tue Jun 20, 2006 12:00 am
Location: Plain City, Ohio
Contact:

Post by CAC » Tue Dec 26, 2006 2:55 pm

Marjan,

I got your example code to work! You suggestion of using the cube is a better approach.

Now, how do I get multiple cubes to show up? I have made line graphs using AddXY to a series. I think I want to have each cube be it's own Series that's color is based on concentration.

Thanks
Craig

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Wed Dec 27, 2006 8:42 am

Hi, Craigh.

I'd derive new series type from one of 3d series and do the drawing in overriden DrawValue method. Bellow is a simple implementation:

Code: Select all

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, TeeSurfa, Series, ExtCtrls, TeeProcs, TeEngine, Chart;

type
  TForm1 = class(TForm)
    Chart1: TChart;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TConcentrationSeries = class (TCustom3DSeries)
    protected
      procedure DrawValue(ValueIndex: Integer); override;
    published
      property Brush;
      property Pen;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TConcentrationSeries }
procedure TConcentrationSeries.DrawValue(ValueIndex: Integer);
var z0,z1: Integer;
    xc,yc: Integer;
    tmpColor: TColor;
begin
  With ParentChart do
  begin
    xc := Axes.Bottom.CalcXPosValue(XValues[ValueIndex]);
    yc := Axes.Left.CalcYPosValue(YValues[ValueIndex]);
    z0 := Axes.Depth.CalcPosValue(0.0);
    z1 := Axes.Depth.CalcPosValue(ZValues[ValueIndex]);

    tmpColor := ValueColor[ValueIndex];
    Canvas.AssignVisiblePen(Pen);
    Canvas.Brush.Style := bsSolid;
    Canvas.Brush.Color := tmpColor;
    Canvas.Cube(xc-3,xc+3,yc-3,yc+3,z0,z1,false);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var ser1: TConcentrationSeries;
begin
  ser1 := TConcentrationSeries.Create(Chart1);
  ser1.ParentChart := Chart1;
  ser1.AddXYZ(2,3,1.5,'',clRed);
  ser1.AddXYZ(1,1,2.5,'',clWhite);
end;

end.
Marjan Slatinek,
http://www.steema.com

Post Reply