Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: janvb on July 27, 2014, 02:45:29 pm

Title: 2D Flowchart
Post by: janvb on July 27, 2014, 02:45:29 pm
hi,

I am new to Lazarus but have desided to give it a go on creating an advanced 2D flow-charting application. I have done similar in C++, but moved to C# because GUI work in C++ is a complicated story. C# works fine except for performance. I have done a few performance/flicker tests on TCanvas and like what I see.

What I am wondering is if anyone can point me to an existing library with source code that could be a good starting point?

What I will do in the first place is to create a generic diagram component specialized on drawing flowchart style diagrams with symbols, linked lines, scrolling, zooming etc.

What I notice from the graphics I have done is that I will need to add smoothing techniques and gradient colors.

One of my questions is if I would be better off using OpenGL as a 2D Canvas?
Title: Re: 2D Flowchart
Post by: Leledumbo on July 27, 2014, 03:56:43 pm
Quote
What I am wondering is if anyone can point me to an existing library with source code that could be a good starting point?
There used to be DrawObjectsExtended (http://tcoq.free.fr/DrawObjectsExtended/DrawObjectsExtendedDesign.html), but it seems to have gone. You might want to try porting components used by this software (https://sourceforge.net/projects/devflowcharter/), though.
Quote
One of my questions is if I would be better off using OpenGL as a 2D Canvas?
Up to you, it could give hardware acceleration but I don't think that's important for a flowchart app.
Title: Re: 2D Flowchart
Post by: taazz on July 27, 2014, 05:15:06 pm
simplegraph can be extended to support any type of diagram. No much has been done on that objective though.
http://sourceforge.net/projects/evssimplegraph/ (http://sourceforge.net/projects/evssimplegraph/)
The main difference bwetween simplegraph and DrawObjects is that simplegraph has everything encapsulated in a single container control  instead of multiple controls that can be used inside any container (most probable candidate is the tscrollbox).
Title: Re: 2D Flowchart
Post by: janvb on July 27, 2014, 09:20:07 pm
Thanks for the help folks.

This is kind of a strange experience after 3 years with C# - I accidentally wrote C#/VB syntax and it works.

(Sender as TControlBox).Canvas...







Title: Re: 2D Flowchart
Post by: Leledumbo on July 28, 2014, 03:43:55 am
Thanks for the help folks.

This is kind of a strange experience after 3 years with C# - I accidentally wrote C#/VB syntax and it works.

(Sender as TControlBox).Canvas...
Object Pascal has it first, remember C#/.NET architect is a former Borland employee who's responsible for Delphi, and previously, Turbo Pascal? He took the concept when M$ bought him, applied M$ism and Cism to it, and tadaaa: C# and .NET framework were born.
Title: Re: 2D Flowchart
Post by: janvb on July 28, 2014, 05:03:17 pm
Object Pascal has it first, remember C#/.NET architect is a former Borland employee who's responsible for Delphi, and previously, Turbo Pascal? He took the concept when M$ bought him, applied M$ism and Cism to it, and tadaaa: C# and .NET framework were born.

Yeah I notice that it is several things that are similar with C#. I am tempted by OpenGL, but will look into that later. I grabbed a TScrollBox and implemented a TFlowChart. A few rounds with crashing IDE before I got the hang of it. The graphics quality will matter because I also need to create instrumentation. I need to work on shape rounding etc - but one thing at a time, I am still crawling here.
Title: Re: 2D Flowchart
Post by: janvb on July 28, 2014, 06:01:07 pm
Is anyone working on improvements to TCanvas to address graphics quality?

This is one thing that is good in C#, but the performance doing graphics on Forms are bad causing noise on the screen. The amount of extra coding I do to deal with secondary problems are not nice. Using WPF is possible, but as Microsoft don't provide a migration path and I need to rewrite stuff anyway - well that's why I am here because I like the idea of multi-platform GUI.

I realize that this is there I might be forced into OpenGL?
Title: Re: 2D Flowchart
Post by: taazz on July 28, 2014, 06:05:52 pm
Is anyone working on improvements to TCanvas to address graphics quality?


Well Graphics quality is a very broad term what are you after specifically an for which widget?
Title: Re: 2D Flowchart
Post by: zamtmn on July 28, 2014, 08:30:05 pm
>>One of my questions is if I would be better off using OpenGL as a 2D Canvas?

I do not think that you will find a suitable component, is likely to have to do everything yourself. Therefore, immediately do ability to paint on canvas and on OpenGL context))
Title: Re: 2D Flowchart
Post by: janvb on July 28, 2014, 09:09:00 pm
Well Graphics quality is a very broad term what are you after specifically an for which widget?

Simple things actually - draw a circle on a TCanvas and I see that antialiasing is not implemented - The BGRA component smooth the curves correctly, but I have not looked into how they do it yet - also many of the components have the same issue so I assumed that is not in the default TCanvas ? I am asking so I don't start working on it if someone else is.
Title: Re: 2D Flowchart
Post by: janvb on July 28, 2014, 09:37:38 pm
Looks like TBGRACanvas etc might contain what I was looking for  :) :-[
Title: Re: 2D Flowchart
Post by: taazz on July 28, 2014, 09:58:33 pm
Simple things actually - draw a circle on a TCanvas and I see that antialiasing is not implemented.

Depends on the widgetset on QT setting the antialised property of the canvas will give you that effect on windows tcanvas is using GDI which does not support antialising but you can create a GDI+ based canvas which supports it but that will be windows only.

Looks like TBGRACanvas etc might contain what I was looking for  :) :-[

Haven't used my self so I can't vouch for its functionality based on what I see on bgrabitmap it should be good enough.
Title: Re: 2D Flowchart
Post by: janvb on July 29, 2014, 12:00:48 am
Haven't used my self so I can't vouch for its functionality based on what I see on bgrabitmap it should be good enough.

We will have to code and try  :D
Title: Re: 2D Flowchart
Post by: Graeme on July 29, 2014, 07:46:22 am
What I am wondering is if anyone can point me to an existing library with source code that could be a good starting point?
...snip....
What I will do in the first place is to create a generic diagram component specialized on drawing flowchart style diagrams with symbols, linked lines, scrolling, zooming etc.

What I notice from the graphics I have done is that I will need to add smoothing techniques and gradient colors.
Take a look at AggPas. It is included with Lazarus, but newer code (slightly more fixes) are included with the fpGUI Toolkit project. It is a Pascal port of the C++ AGG (Anti-Grain Geometry) framework. It does very high quality anti-aliasing, sub-pixel redering, alpha blending etc. It is 100% Object Pascal, so is very portable, and doesn't rely on any other frameworks like XLib, GDI etc.

I've attached a small screenshot sample of AggPas painting in a fpGUI demo. The AggPas directory contains 30+ demos that are very impressive. See the URL "Original AggPas demo page" for many more screenshots and demo binaries you can download.

AggPas in fpGUI: [https://github.com/graemeg/fpGUI/tree/master/src/corelib/render/software (https://github.com/graemeg/fpGUI/tree/master/src/corelib/render/software)]
fpGUI Toolkit: [https://github.com/graemeg/fpGUI (https://github.com/graemeg/fpGUI)]
Original AggPas demo page: [http://www.crossgl.com/aggpas/aggpas-demo.htm (http://www.crossgl.com/aggpas/aggpas-demo.htm)]
Title: Re: 2D Flowchart
Post by: janvb on July 29, 2014, 09:12:15 am
Take a look at AggPas....

Thanks, I will.

Title: Re: 2D Flowchart
Post by: janvb on July 31, 2014, 11:37:56 pm
I am a bit puzled by graphics performance in C# compared to FPC.

This flowchart component exist in C# and FPC now. The FPC one feels fast at start and get slower as you add symbols to draw - at my computer it start getting slow at ca 700 symbols. The C# version is much slower at start, but is still going strong with the same speed at 1700 symbols.

Obviously the rendering in .NET must be very good compared to native Windows.

I should note that if I run the C# on my dell with 8 cores it have problems even at 10 symbols because the CPU slows down the frequency when it's on batteries. This test was on an older 2-core at faster frequency - and .NET Forms is very dependant on a single core for GUI work.
Title: Re: 2D Flowchart
Post by: Graeme on July 31, 2014, 11:51:53 pm
What exactly are you using to draw your graph when using Free Pascal? Straight LCL, BGRAGraphics, AggPas, fcl-image?  Are you continuously drawing and refreshing the display, or do you first paint in memory, then blit the image to the screen?
Title: Re: 2D Flowchart
Post by: engkin on July 31, 2014, 11:55:53 pm
Without some source code, it is hard to tell if you used the right method. Have you seen this page (http://wiki.lazarus.freepascal.org/GraphicTest)?
Title: Re: 2D Flowchart
Post by: elraymonds on August 01, 2014, 09:11:26 am
You can use a flowchart software (http://creately.com/Flowcharts-and-Workflow-Diagrams-Online) to create your flowchart diagram, then convert it to xml and embed it to your code. works for me
Title: Re: 2D Flowchart
Post by: janvb on August 01, 2014, 12:39:00 pm
You can use a flowchart software (http://creately.com/Flowcharts-and-Workflow-Diagrams-Online) to create your flowchart diagram, then convert it to xml and embed it to your code. works for me

They have some nice work indeed. Sadly I need the full editor embedded on the desc-top + I want something I have the sorce code to so I am guaranteed it can do what I want.
Title: Re: 2D Flowchart
Post by: janvb on August 01, 2014, 02:29:13 pm
What exactly are you using to draw your graph when using Free Pascal? Straight LCL, BGRAGraphics, AggPas, fcl-image?  Are you continuously drawing and refreshing the display, or do you first paint in memory, then blit the image to the screen?

My first test was to draw rounded rectangles directly on TCanvas from a TScrollBox - in this stage I manage 10,000. As soon as I add text it drops to 800ich. This is not exact measurements it is more a indication of the point where I feel the editor get sticky and less nice to work with. I did set DoubleBuffered, but realized that did little + flicking is not my issue here. The screen is close to flicker free.

Without some source code, it is hard to tell if you used the right method. Have you seen this page (http://wiki.lazarus.freepascal.org/GraphicTest)?

I added BGRABitmap now, but the performance I get with antialiasing on is that it start getting sticky at 100-200ich symbols. I am testing with rounded rects without text as you can see below. I really like the quality of the BGRABitmap, but I am a bit concerned over my performance at the time being.

I will attempt an implementation based on BGRABitmap and see what I end up with. The real diagram will render and symbols are usually spread out so the behaviour will be nice at 1:1 zoom, but the problem is as the user zoom on large diagrams.

I have included my performance test below - This is just a brute force test to get a feeling about performance limitatioons and the path forward, but please feel free to suggest.

procedure TFlowChart.Paint;
var
    img:TBGRABitMap;
    x,zx :Integer;
    line: TBGRAPixel=(blue: 255; green: 0; red: 0; alpha: 255);
    back: TBGRAPixel=(blue: 255; green: 255; red: 0; alpha: 255);
begin
    Img := TBGRABitmap.Create(ClientWidth, ClientHeight, BGRAWhite);

    // draw grid
    x:=-1;
    while x < 2000 do
    begin
      x:=x+gridSize;
      zx:=x;//Round(x*zoom);
      img.DrawHorizLine(0,zx,2000,BGRABlack);
      img.DrawVertLine(zx,0,2000,BGRABlack);
    end;

    // draw n symbols brute force
    for x:=1 to 200 do
    begin

      Img.RoundRectAntialias(x,y,x+100,x+50,20,20,line,1,back);

    end;

    Img.Draw(Canvas, 0, 0, True);
    Img.Free;

end;     

Also thanks for all the  feedback and help. It is very nice for a newbie like myself to see that the community is stretching out to help.
Title: Re: 2D Flowchart
Post by: Laksen on August 01, 2014, 02:38:52 pm
Try to only allocate the bitmap once. Allocating it for each frame will be very slow.

Just clear it in the start of the Paint routine instead.
Title: Re: 2D Flowchart
Post by: Graeme on August 01, 2014, 02:50:38 pm
Yup, allocating a bitmap on every paint is a BIG performance killer.
Title: Re: 2D Flowchart
Post by: janvb on August 01, 2014, 11:13:25 pm
Try to only allocate the bitmap once. Allocating it for each frame will be very slow.

Just clear it in the start of the Paint routine instead.

Agree, but it makes marginal difference in this case.

The snip below and the call to RoundRectAntialias is responsible for 99% of the performance issue. It behaves nice with 1 to ca 50, but start getting sticky from there and up.

    for x:=1 to 200 do
    begin

      img.RoundRectAntialias(x,x,x+100,x+50,20,20,line,1,back);

    end;

I am wondering if I am doing something utterly wrong ?
Title: Re: 2D Flowchart
Post by: Graeme on August 05, 2014, 05:37:21 pm
I have included my performance test below - This is just a brute force test

Attached is a AggPas version of your demo. Though I am still not sure how you actually do your tests and limitations.  Can you post a screenshot of what you actually want to accomplish?

Either way, here is a AggPas console version (no fpGUI dependencies, hence the drawing API is  more complex looking). I painted 200 rounded rectangle in 468ms. In comparison, 200 standard rectangles take 20ms less, so rounded or not doesn't really make a difference to AggPas. Drawing 10,000 rounded rectangles completed in 800ms.

Some notes:
  The rectangle lines are painted with alpha suppport for good measure (solid lines look so ugly). I also painted with a 2 pixel width line. AggPas supports sub-pixels too, so for fine lines you can paint with a 0.4 pixel width if you want. :)

NOTE:

Code: [Select]
c:\devel\tests>console_aggpas_graphtest.exe
Grid drawing: time spent: 00.016
Rounded rect drawing: time spent: 00.452
Total time: 00.468

I've also attached the PNG image this example app generates.

Edit:
Here is the results of the same application running on my desktop PC using 64-bit FreeBSD. As expected, quite a bit faster than my work laptop.
Code: [Select]
[aggpas_console]$ ./console_aggpas_graphtest
Grid drawing: time spent: 00.006
Rounded rect drawing: time spent: 00.136
Total time: 00.142
Title: Re: 2D Flowchart
Post by: janvb on August 06, 2014, 12:38:31 pm
Thanks. I will disect that then I get home. What I want to achieve is a path forward on graphics that satisfy my requirements for quality and performance. The 2d flowchart is only a test case because it expose what I want to see. In my version I also have scrolling and zooming. If it can handle those it will handle real-time instrumentation.
Title: Re: 2D Flowchart
Post by: janvb on August 14, 2014, 03:36:08 pm
Attached is a AggPas version of your demo. Though I am still not sure how you actually do your tests and limitations.  Can you post a screenshot of what you actually want to accomplish?

I compiled and ran your test, but I don't see any drawings?
Title: Re: 2D Flowchart
Post by: zamtmn on August 14, 2014, 08:27:20 pm
janvb
Take a look also at ZCAD http://sourceforge.net/projects/zcad/ It's not quite 2D Flowchart, but complete vector editor.
Simple graphics program based on ZCAD engine - http://sourceforge.net/projects/zcad/files/simplecad.7z/download
Title: Re: 2D Flowchart
Post by: Graeme on August 15, 2014, 12:12:44 am
I compiled and ran your test, but I don't see any drawings?
It's a console program that generates a PNG image of the same name as the application. It was a quick and simple example to enable me to time AGGPAS drawing speed from start to end. The drawing code was based on your BGRABitmap example.
Title: Re: 2D Flowchart
Post by: janvb on August 16, 2014, 04:53:07 pm

It's a console program that generates a PNG image of the same name as the application. It was a quick and simple example to enable me to time AGGPAS drawing speed from start to end. The drawing code was based on your BGRABitmap example.

Keep in mind that I am new to FPC, how do I get started with fpGUI w/Aggpas on a TForm? Do you have any getting started turorial?
Title: Re: 2D Flowchart
Post by: engkin on August 16, 2014, 07:47:25 pm
After DrawStuff(agg), Buf holds the data of the image. Convert the data to the pixel format of your destination. Here is some code you can use to test it on a TImage:
Code: [Select]
{
uses
 ..., ExtCtrls, Graphics;
...
procedure BufToImage(const buf:array of int8; image: TImage);
var
  pdst: PByte;
  psrc: PCardinal;
  x, y: Integer;
  c: TColor;
  sizeOfOneRowInBytes: cardinal;
  sizeOfOnePixelInBytes:integer;
begin
  image.Picture.Bitmap.SetSize(ImageWidth, ImageHeight);

  //support for pf24bit or pf32bit pixel formats
  sizeOfOnePixelInBytes := PIXELFORMAT_BPP[image.Picture.Pixmap.PixelFormat] div 8;// 3 or 4 bytes
  sizeOfOneRowInBytes := ImageWidth * sizeOfOnePixelInBytes;

  pdst := image.Picture.Bitmap.RawImage.Data+sizeOfOneRowInBytes*(ImageHeight-1);
  psrc := @buf[0];
  for y := 0 to ImageHeight - 1 do
  begin
    for x := 0 to ImageWidth - 1 do
    begin
      //switch places between red and blue bytes;
      c := (psrc^ and $0000FF00) or (RolDWord(psrc^, 16) and $00FF00FF);
      PCardinal(pdst)^ := psrc^;

      inc(pdst, sizeOfOnePixelInBytes);
      inc(psrc, 1);
    end;
    dec(pdst, 2*sizeOfOneRowInBytes);
  end;
end;

It works for me on Windows.
Title: Re: 2D Flowchart
Post by: Graeme on August 17, 2014, 02:10:51 am
Keep in mind that I am new to FPC, how do I get started with fpGUI w/Aggpas on a TForm? Do you have any getting started turorial?
There is no "getting started" tutorial, but I am working on one. I've already got various chapter ideas and some text down.

Do you already understand how to create a basic fpGUI application? If not, take a look at the <fpgui>/examples/gui/ directory for many small demos. If you are using Lazarus IDE, you can register a new project type by installing <fpgui>/extras/lazarus_ide/fpgui_ide.lpk package. An fpGUI project can then be created by going to "File -> New... -> Project -> fpGUI Application". All applications and demos included with fpGUI contains Lazarus Project files, so you can just open and compile them too.

Using AggPas with fpGUI.
There are two options.

1.  There is experimental support which makes AggPas the default backend for fpGUI - thus any existing fpGUI application will automatically use AggPas. Everything is then painted with AggPas and you use the TfpgCanvas as normal. After enough testing this will eventually become the default backend on all platforms. To enable this you need to enable the AggCanvas compiler define in the fpgui_toolkit.lpk package and recompile that package. Open the package then go to its Compiler Options -> Other and remove the "X" after the line -dAggCanvas

2.  Alternatively you can use the normal X11 or GDI backends of fpGUI, and only use AggPas to paint to a bitmap which you can then paint somewhere on the screen (or save to a file). Do do this, create an instance of TAgg2D and create a instance of TfpgImage. The image will become the output buffer of whatever you paint with AggPas. To tell TAgg2D about the image, call the TAgg2D.Attach() method. Now simply paint using the available methods of the TAgg2D class. Documentation for the TAgg2D class can be found at <fpgui>/docs/aggpas/agg2d.html

I hope this is enough to get you started. If you want more support don't hesitate to ask. You can also join the official fpGUI support newsgroup where more people will be able to answer and learn from your questions. Details connecting the fpgui.support newsgroup can be found there [http://fpgui.sourceforge.net/support.shtml (http://fpgui.sourceforge.net/support.shtml)]
Title: Re: 2D Flowchart
Post by: janvb on August 22, 2014, 05:04:48 am
Thanks for this and all the help so far.

At present I decided to ignore presentation quality because I have my own TZoomCanvas that easily can be modified to use something else than core LCL to draw graphics later.

I create diagrams with a special functionality, and it's more important to get the engine up running for now so I can move on to what I wanna use it for - it also leaves the doors open so that people who favor BGRABitmap, fpGUI or other libraries easily can do a minor port later.

TinyPortal © 2005-2018