[Solved] Polygons with user-defined appearance. lazarus / 39-Graphics ---------------------------------------------------------------------- loaded · 2023-05-17 13:19 Hi All, How can we easily draw a polygon with a custom line type and fill shape including the symbol view? How to draw a polygon in a sample picture? Note : I created the polygon myself by hand. There may be problems with the beginning and ending of the shaped lines. ---------------------------------------------------------------------- wp · 2023-05-17 15:02 Use the Brush's Bitmap property to define the brush's fill pattern. As for the pen pattern, I only know of dash/space patterns defined by the SetPattern method (1st, 3rd, 5th etc argument = dash length, 2nd, 4th, 6th etc argument = spacing). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  FPCanvas; var  FillBmp: TBitmap;procedure TForm1.PaintBox1Paint(Sender: TObject);begin  Paintbox1.Canvas.Brush.Color := clWhite;  Paintbox1.Canvas.Brush.Bitmap := nil;  Paintbox1.Canvas.FillRect(0, 0, Paintbox1.Width, Paintbox1.Height);   Paintbox1.Canvas.Brush.Style := bsImage;  Paintbox1.Canvas.Brush.Bitmap := FillBmp;  Paintbox1.Canvas.Pen.Style := psPattern;  Paintbox1.Canvas.Pen.SetPattern([45, 5, 15, 5]);   // even index = dash length, odd index = spacing  Paintbox1.Canvas.Pen.Width := 3;  Paintbox1.Canvas.Rectangle(0, 0, 300, 200);end; procedure TForm1.FormCreate(Sender: TObject);var  x, y: Integer;begin  FillBmp := TBitmap.Create;  FillBmp.SetSize(16, 16);  FillBmp.Canvas.Brush.Color := clWhite;  FillBmp.Canvas.FillRect(0, 0, FillBmp.Width, FillBmp.Height);  for y := 0 to FillBmp.Width - 1 do  for x := 0 to FilLBmp.Height - 1 do    begin      if (x+y) mod 16 in [0, 4] then        FillBmp.Canvas.Pixels[x, y] := clRed;      if ((FillBmp.Width - x) + y) mod 16 in [0, 6] then        FillBmp.Canvas.Pixels[x, y] := clBlue;    end;end; procedure TForm1.FormDestroy(Sender: TObject);begin  FillBmp.Free;end; If you want to draw bitmaps along the line I think you must follow the line manually. ---------------------------------------------------------------------- loaded · 2023-05-17 15:38 Thank you very much for your answer, wp. Yes, I am one step closer to what I want. I guess the brush doesn't support transparency. Is it true ? Any help would be greatly appreciated. Respects. ---------------------------------------------------------------------- wp · 2023-05-18 16:22 Spent some time with the issue and found that transparency works on Linux, but not on Windows, even if the pattern bitmap is provided with alpha channel. Updated the demo project "pen_brush" coming with Lazarus to work with user-defined patterns. Since this is in the Laz/main branch I am attaching it as a zip. BTW, the pattern bitmap in your screenshot should not be rotated; this is because the crossing point are moving down when going from left to right. This is the reason with the images do not perfectly match. If you need the pattern rotated the pattern bitmap should have a width such that the next crossing point comes in at the correct height again (hard to explain...). Maybe like in the attachment (The left/top corner is in the center of a crossing point, and the right/top corner as well; and the left/bottom corner is a bit after a crossing, and the right/bottom corner about the same amount before the crossing point - well, maybe not 100% exact, I extended the images in image processing software...). ---------------------------------------------------------------------- loaded · 2023-05-18 21:05 Thank you as much as the number of seconds in the time you spent preparing the demo. I will do a detailed study on this subject tomorrow, I hope I can make progress. ---------------------------------------------------------------------- loaded · 2023-05-19 06:55 I could not solve the transparency problem in all my experiments. I haven't dealt with the problem of changing the linetype yet. I heard today that an application I'm aware of (a delphi application I think) can do this in windows. Maybe he used a different method. But what could it be?  Just to try this, before installing the trial version of Delphi, if there is a friend with the current Delphi Version installed, I would be very grateful if he could test and inform us. Respects. ---------------------------------------------------------------------- circular · 2023-05-19 08:39 You could use BGRABitmap to have transparent pattern. ---------------------------------------------------------------------- loaded · 2023-05-19 12:38 Quote from: circular on May 19, 2023, 10:39:59 amYou could use BGRABitmap to have transparent pattern. circular , thank you very much for your reply. Yeah, I don't know why I didn't think of that. I got a little closer to the solution in the scanning problem. Now, at the point of line shape, which is the other important issue, will BGRA be able to pull a rabbit out of the hat? ---------------------------------------------------------------------- wp · 2023-05-19 14:37 If you want to trace the polylines by bitmaps drawn evenly along the line segments you could use the attached TLinestepper: You create it with the distance between the bitmap symbols specified in the constructor, move to the first point of the polyline by calling the MoveTo method and then advance to the next point by calling StepTo (which hads an additional parameter whether the symbol should be drawn at the end of the last segment). Drawing itself must occur in the handler of the OnStep event. See attached demo. ---------------------------------------------------------------------- loaded · 2023-05-19 14:57 Thank you very much for the wp example. But still, I can't thank you enough. If you were here, I would offer you a cup of tea.  Yes, I was thinking of doing something like this if I couldn't find any built-in methods. The only drawback of this method is that it does not rotate the bitmap according to the angle of the line. This can be done by hand but requires some polar calculation. I'll handle the rest. Much respect. ---------------------------------------------------------------------- BobDog · 2023-05-19 17:17 Some random polygons and styles: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  {$mode fpc}usesptcGraph, ptcCrt,  SysUtils,math;   Type Point=objectx,y:double;End; type aop=array of point;    function circulate(var p:aop):point;       procedure swap(var a, b: point);    var temp: point;     begin     temp := a; a := b; b := temp;     end;       var    p1,p2,i:integer;    c:point;    begin    c.x:=0;c.y:=0;   for i:=0 to high(p) do     begin    c.x:=c.x+p[i].x;    c.y:=c.y+p[i].y;    end;    c.x:=c.x/length(p);    c.y:=c.y/length(p);For p1 := 0 To high(p)-1 dobegin    For p2 := p1 + 1 To high(p) do    begin        if arctan2(p[p1].y-c.y,p[p1].x-c.x)< arctan2(p[p2].y-c.y,p[p2].x-c.x) then        begin            swap (p[p1],p[p2]);            end;         end;         end;         exit(c);end;    function range(mymin:int64;mymax:int64):int64;       begin      exit(trunc(int((Random*(Mymax-mymin+1)))+MyMin));   end;     procedure drawpolygon(ret:aop;linecol:integer);    var    n:integer;    c:point;    begin    c:=circulate(ret);    for n:=0 to high(ret)-1 do    line(trunc(ret[n].x),trunc(ret[n].y),trunc(ret[n+1]. x),trunc(ret[n+1].y));    line(trunc(ret[high(ret)].x),trunc(ret[high( ret)].y),trunc(ret[0].x),trunc(ret[0].y));    floodfill(trunc(c.x),trunc(c.y),linecol );    end;           var a:aop=nil; gd, gm: SmallInt; ch:char; i,j:integer; style:array[1..8] of word;   begin{==========  set up graph =========}      gd := D8bit;      gm :=  m800x600;      InitGraph(gd, gm, '');      if GraphResult <> grok then  halt;      settextstyle(BoldFont,HorizDir,1);      setwri]"]>Blockedde(copyput);      setbkcolor(blue);      for i:=1 to 8 do style[i]:=i;          repeat     ClearViewPort;     setcolor(15);     outtextxy(10,40,'Space key to refresh -- esc key to end.');      setlength(a,range(3,12));        for i:=0 to high(a) do    begin      a[i].x:=(range(0,800));      a[i].y:=range(0,600);      end;       setfillstyle(style[range(1,8)],range(2,15));       j:=range(2,15);        setcolor(j);      drawpolygon(a,j);       ch:=readkey;        until (ord(ch)= 27);       closegraph;      end. ---------------------------------------------------------------------- circular · 2023-05-19 17:27 Quote from: loaded on May 19, 2023, 02:38:13 pmcircular , thank you very much for your reply. Yeah, I don't know why I didn't think of that. I got a little closer to the solution in the scanning problem. Now, at the point of line shape, which is the other important issue, will BGRA be able to pull a rabbit out of the hat? Yes you could use TBGRAPath cursor to go forward each step along the way. ---------------------------------------------------------------------- zamtmn · 2023-05-19 19:42 Within zcad I solved the problem of vector line types and vector hatching https://forum.lazarus.freepascal.org/index.php/topic,59419.0.html (dxf use it). I haven't found any other ways except to count all intersections and characteristic points mathematically and draw it. It works and is even fast ---------------------------------------------------------------------- loaded · 2023-05-19 20:19 BobDog, circular and zamtmn Thank you to each and every one of you for taking your precious time to reply. BobDog ; I went to the old days, it reminded me of the screen savers on the dos screen. The scanning problem was solved, there was a line problem, the example you gave, I could not see a solution for this issue circular ; I've gone through all the demos of bgrabitmap but couldn't find an example of using TBGRAPath. Just the code you gave in the https://foru m.lazarus.freepascal.org/index.php/topic,58812.msg438432.html#msg43843 2. It works but I couldn't understand the logic. I think I'll try again tomorrow with a fresh head. A proverb "It is good to repeat, even 180 times" zamtmn ; Congratulations on solving the problem and also demonstrating its solvability. ---------------------------------------------------------------------- circular · 2023-05-20 06:29 The TBGRAPath objet takes a series of instructions to draw a path in a similar way as with HTML canvas. To define a polygon, you can call moveTo(x,y) to define the first point, and then lineTo(x,y) for each subsequent point. Finally you can call closePath to end the polygon. Once the path is created, you can draw it and fill it, either using its stroke and fill functions, or by calling TBGRABitmap.DrawPath or FillPath functions. Do draw a symbol along the path, you can use TBGRAPath.CreateCursor() function to create a cursor. The cursor has MoveForward and MoveBackward for example to move along the path. They return the actual moved length, which will be 0 when the end of the path has been reached. The CurrentCoordinate property contains the current position and the CurrentTangent contains a unit vector to align the shape. There is an example of using the path and cursor in bspline project that you will find in the tests: https://github.com/bgrabitmap/bgrabitmap/tree/master/test/bgraaggtest ---------------------------------------------------------------------- circular · 2023-05-20 07:10 Here is a sample project ---------------------------------------------------------------------- loaded · 2023-05-20 07:56 Yes, it was very good that you gave the concise explanation first and then gave an example. Thanks to you, I'll put the Tetris pieces in place a little easier. I hope I can handle the rest myself. It is worth mentioning; My impression when running the demos. How sad that we are not aware of the existence of a graphic treasure at our disposal. I think you're the superman of the graphic world. Thank you for the tremendous work and effort you put into creating BGRA. ---------------------------------------------------------------------- circular · 2023-05-20 08:01 Glad that the explanation and example will help you start  I did put a lot of effort in this library. It is true that the documentation is not very much complete. Now that I am thinking, maybe it could be worth adding those examples in the wiki, at least a summary or something. ---------------------------------------------------------------------- loaded · 2023-05-20 08:09 Yes, what has been done at BGRA is beyond our dreams. BGRA needs a good showcase face and detailed documentation. Otherwise, he will disappear in the flow of life like a genius child in a home for the orphans... ---------------------------------------------------------------------- circular · 2023-05-20 09:34 Yes, I did not have much time to document things. I was hoping to get help from the community. Here I made a draft for the bgraaggpas folder projects: https://wiki.freepascal.org/BGRABitmap_AggPas At least one can have a quick look at those beautiful projects ---------------------------------------------------------------------- loaded · 2023-05-20 10:54 Quote from: circular on May 20, 2023, 11:34:47 amAt least one can have a quick look at those beautiful projects  Yes, I was one of those peeking. Thank you also for this useful work. Health to your hands.