Recent

Author Topic: 3D on TAChart  (Read 10401 times)

bigeno

  • Full Member
  • ***
  • Posts: 247
3D on TAChart
« on: March 06, 2014, 05:19:14 pm »
Is there any way to provide 3D Chart ? I need AxisX AxisY and AxisZ for this ? in the present state of tachart this can be done?

wp

  • Hero Member
  • *****
  • Posts: 6367
Re: 3D on TAChart
« Reply #1 on: March 06, 2014, 05:24:24 pm »
No, currently this is not possible with TAChart. What you might do is call gnuplot from your program, catch the generated diagram and show it in a TImage.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

bigeno

  • Full Member
  • ***
  • Posts: 247
Re: 3D on TAChart
« Reply #2 on: March 06, 2014, 05:30:15 pm »
thx, but I was thinking if that could be possible, somehow convert XYZ points to 2D and manage to connect with ZPosition of Chart ?

bigeno

  • Full Member
  • ***
  • Posts: 247
Re: 3D on TAChart
« Reply #3 on: March 06, 2014, 05:41:31 pm »
Some OT,
I read license of gnuplot, and maybe you cant point me,can I use gnuplot binaries and redistribute with instalation of my commercial application ?

wp

  • Hero Member
  • *****
  • Posts: 6367
Re: 3D on TAChart
« Reply #4 on: March 06, 2014, 08:21:45 pm »
Quote
manage to connect with ZPosition of Chart
ZPosition is something else. It controls the order axes or series are drawn, it does not have anything to do with 3D.

Quote
can I use gnuplot binaries and redistribute with instalation of my commercial application
I'm no lawyer, but I'd say you can. The license document says "Permission to use, copy, and distribute this software and its documentation for any purpose with or without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation."

Do you want interactive 3D charts like interactive changing of viewpoint etc? In this case the gnuplot solution will be a bit clumsy. If not, give me some time to prepare a simple demo.

Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

bigeno

  • Full Member
  • ***
  • Posts: 247
Re: 3D on TAChart
« Reply #5 on: March 06, 2014, 09:28:14 pm »
Thanks for taking some time. I just only need something like attached image (from tachart demo) but points with respect and proper scalling to one more AxisZ

wp

  • Hero Member
  • *****
  • Posts: 6367
Re: 3D on TAChart
« Reply #6 on: March 07, 2014, 12:10:34 am »
Here's a little demo that creates a gnuplot script, calls gnuplot and shows the output file in a TImage component.

For testing, create a new project, add a TImage and a TButton to the form, and assign this code to the button's OnClick:

Code: [Select]
procedure TForm1.BtnPlotClick(Sender: TObject);
const
  NX = 30;
  NY = 30;
  XMIN = -10;
  XMAX = 10;
  YMIN = -10;
  YMAX = 10;
var
  prc: TProcess;
  script: TStringList;
  i,j: Integer;
  x,y,z,r: Double;
  tmpfile: String;
  pngfile: String;
begin
  pngfile := ExtractFileName(ChangeFileExt(GetTempFilename('.', 'IMG'), '.png'));

  prc := TProcess.Create(nil);
  try
    script := TStringList.Create;
    try
      // Prepare gnuplot to write to a png file
      script.Add(Format('set terminal png size %d, %d', [Image1.Width, Image1.Height]));
      script.Add(Format('set output "%s"', [pngfile]));

      // Chart title
      script.Add('set title "my first 3d plot"');

      // Plot command
      script.Add('splot "-" using 1:2:3 with points \');

      // create some data; append them to script (by using 'file name' parameter "-")
      DefaultFormatSettings.DecimalSeparator := '.';
      for i:=0 to NX-1 do begin
        x := XMIN + (XMAX - XMIN) * i / (NX - 1);
        for j:=0 to NY-1 do begin
          y := YMIN + (YMAX - YMIN) * j / (NY - 1);
          r := sqrt(x*x + y*y);
          if r = 0 then
            z := 0
          else
            z := sin(r)/r;
          script.Add(Format('%f %f %f', [x, y, z]));
        end;
      end;
      script.Add('end');    // this closes the data section

      tmpfile := GetTempFileName('.', 'TEMP');
      script.SaveToFile(tmpfile);
    finally
      script.Free;
    end;

    // run gnuplot and execute the script
    prc.Executable := 'd:\programme\gnuplot\bin\gnuplot.exe';
    prc.Parameters.Add(tmpfile);
    prc.Options := prc.Options + [poWaitOnExit];
    prc.Execute;

    // load image created by the script into the TImage component
    Image1.Picture.LoadfromFile(pngfile);

  finally
    prc.Free;
    DeleteFile(pngFile);
    DeleteFile(tmpFile);
  end;
end;

Have a look at the gnuplot docs for further refinements of the script. Note that this script does contain the data directly. If your data are in a file you can specify the filename instead of the "-" parameter of the "splot" command.
« Last Edit: March 07, 2014, 12:12:44 am by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

bigeno

  • Full Member
  • ***
  • Posts: 247
Re: 3D on TAChart
« Reply #7 on: March 07, 2014, 05:27:10 pm »
Big THX for this example, works ok.  :D

mtanner

  • Full Member
  • ***
  • Posts: 226
Re: 3D on TAChart
« Reply #8 on: July 22, 2017, 09:39:03 am »
I thought this item looked just what I want - to call gnuplot from my program and retrieve the chart produced. But I cannot get it to work.

Installed gnuplot. Tested it worked with a simple "plot sin(x)".

Created a test Lazarus program using the code above. (Also assigned the SCRIPT to a TMemo so I could check the script being created.)

When I click the plot button I can see the gnuplot console window flash up then disappear. Too quick to read, but doing it repeatedly I can just about make out that it's showing a single line, an error message which I think says it cannot open the image file.

How can I make the gnuplot window not close, so I can read the messages more reliably?

Is this code still current - there seem to be more than one gnuplot...  exe files in the current gnuplot distribution, am I using the right one?

I didn't understand why the GetTempFileName has a first parameter of ".", which just gives an invalid filename. So I changed it to a specifix directory, or to null.

wp

  • Hero Member
  • *****
  • Posts: 6367
Re: 3D on TAChart
« Reply #9 on: July 22, 2017, 10:56:30 am »
Maybe you did not understand what this example is doing: It creates a script for gnuplot, starts gnuplot, executes the script, gnuplot writes its output to a temporary image file, and the program reads the image file and displays it in a TImage. I just tested this old sample again, now with the current 5.2RC2, and it still is working perfectly.

So, it is not intended to show the gnuplot window permanenty. Even flashing up is annoying - it can be suppressed if poNoConsole is added to the options of the process (in addition to poWaitOnExit). If you really want to keep gnuplot open you must prevent destroying its process (prc.Free) - of course, this still must be done a some time, and therefore, you must change the structure of the program considerably.

If your script has errors, or if you want to learn how to work with gnuplot, it is better to call gnuplot interactively. On Windows the most convenient exe is wgnuplot.exe. It opens an interactive commandline window in which you can type in gnuplot commands, and plots are shown in a separate window. To plot the sin function, type

Code: [Select]
plot sin(x)
To execute the script file type

Code: [Select]
load "filename_of_the_script"
If the script file is not found you first must chdir to the directory containing the script file (or start wgnuplot.exe from there). The command for changing directories is chdir, but note that the path must be quoted and even on Windows forward slashes must be used as path delimiters.

Code: [Select]
chdir "c:/prog_lazarus/gnuplot_demo"
To avoid that the temporary script file is erased in the demo after execution of gnuplot just comment the line "DeleteFile(tmpFile)". The script file is found in the current directory. Since this is easier to find than the "official" TEMP directory of the OS, I decided to use the overloaded version of GetTempFile which wants the destination directory as first parameter and put '.' in there, because '.' means: current directory.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

mtanner

  • Full Member
  • ***
  • Posts: 226
Re: 3D on TAChart
« Reply #10 on: July 22, 2017, 11:24:49 am »
I'll have another look thanks.  I did understand what the example is supposed to do - it's exactly what I want to do. In practice you do not want the gnupolot window to hang around, but when things are not working it would be useful to see what errror messages are being displayed by gnuplot. I tried adding "-persist" to the options for the TProcess, but that seemed to have no effect.

It's very useful that you have verified it still works - I had been wonderng if some small thing had changed in gnuplot since you write the example.

wp

  • Hero Member
  • *****
  • Posts: 6367
Re: 3D on TAChart
« Reply #11 on: July 22, 2017, 12:45:24 pm »
I see, I had similar issues in a program at work. Please see the attached gnuplotter which
  • starts gnuplot in its own thread making it possible to abort gnuplot if it's waiting for input
  • catches the gnuplot error messages.
The shellcommandrunner unit is (probably) taken from here: http://forum.lazarus.freepascal.org/index.php/topic,17315.msg96820.html#msg96820
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

mtanner

  • Full Member
  • ***
  • Posts: 226
Re: 3D on TAChart
« Reply #12 on: July 22, 2017, 01:11:36 pm »
I had another go at getting the sample code to work. I found that if, instead of the £d plot in the sampl, I just used a simple "plot sin(x)", then the mechanism for calling gnuplot and retrieving the image seemed to work fine. That suggests I've got something wrong in setting up the 3D data.

mtanner

  • Full Member
  • ***
  • Posts: 226
Re: 3D on TAChart
« Reply #13 on: July 22, 2017, 01:30:10 pm »
It's my eyesight! For tedious reasons I'm developing code on a different system to the one I'm browsing on. So I had to manually transcribe the code. Not (yet) being very familiar with gnuplot, I copied the "-" in the splot command as a ".", which seems to be what caused the failure. Correcting this makes it all work. So now I have a whole new graphics capability available.

Sometimes, instead of retrieving the image, I'd like to start gnuplot, pass it the script, and leave it running. Is this possible?

wp

  • Hero Member
  • *****
  • Posts: 6367
Re: 3D on TAChart
« Reply #14 on: July 22, 2017, 01:53:21 pm »
Certainly - everything is possible. You must avoid that the process in which gnuplot is running is terminated, and you must keep track of the process variable because at some time you'll want its window to disappear. This will be more complicated, I leave the solution to you because I would not do it like this. For developing a script I'd use gnuplot directly (wgnuplot with its standard windows interface in which many gnuplot commands are accessible as menu items, or gnuplot directly). Or use the gnuplotter a few posts above where you type the script into a memo, click Execute, and either get the plot image or the original gnuplot error message.

For learning gnuplot, the book "Gnuplot in action" (https://cds.cern.ch/record/1359227/files/9781933988399_TOC.pdf) is a good read. Or maybe look at http://people.duke.edu/~hpgavin/gnuplot.html, or - if you are a friend of videos - https://www.youtube.com/watch?v=9k-l_ol9jok.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10