3

I've been searching this quite a while but couldn't get the answer.

I want to draw a polygon on an image, but I want to do this with by creating points; With the MouseCursor create this specific points, and with a button draw a line along these points;

I found this:

var
  Poly: array of TPoint;
begin  
   // Allocate dynamic array of TPoint
   SetLength(Poly, 6);

  // Set array elements
  Poly[0] := Point(10, 10);
  Poly[1] := Point(30, 5);
  Poly[2] := Point(100, 20);
  Poly[3] := Point(120, 100);
  Poly[4] := Point(50, 120);
  Poly[5] := Point(10, 60);

  // Pass to drawing routine
  Canvas.Polygon(Poly);

  // Redim if needed
  SetLength(Poly, 7);
  Poly[6] := Point(1, 5);

  // Pass to drawing routine
  Canvas.Polygon(Poly);
end;

This is what I want, but the difference is the Point[1], Point[2], etc is given by the user with a MouseEvent.

TLama
  • 75,147
  • 17
  • 214
  • 392
Fruit
  • 33
  • 1
  • 6

2 Answers2

4

You might superimpose a Paintbox over your image and use a code like this

unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TPointArray=array of TPoint;
  TForm3 = class(TForm)
    Image1: TImage;
    PaintBox1: TPaintBox;
    Button1: TButton;
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1Paint(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    FPointArray:TPointArray;
  public
    { Public-Deklarationen }
  end;
var
  Form3: TForm3;
implementation
{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
begin
   PaintBox1.Visible := false;
   Image1.Canvas.Polygon(FPointArray);
end;

procedure TForm3.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   SetLength(FPointArray,Length(FPointArray)+1);
   FPointArray[High(FPointArray)].X := X;
   FPointArray[High(FPointArray)].Y := Y;
   Paintbox1.Invalidate;
end;

procedure TForm3.PaintBox1Paint(Sender: TObject);
var
 i:Integer;
begin
  PaintBox1.Canvas.Brush.Style := bsClear; //as suggested by TLama
  PaintBox1.Canvas.Polygon(FPointArray);
  for I := 0 to High(FPointArray) do
      begin
        PaintBox1.Canvas.TextOut(FPointArray[i].X-5,FPointArray[i].y-5,IntToStr(i));
      end;
end;

end.
bummi
  • 27,123
  • 14
  • 62
  • 101
  • hello bummi, I really liked you're idea. I had to declare FPointArray:TPointArray; as `FPointArray : array of Tpoint`. the projects works fine, but how do I make it for the polygon not paint its area? just draw the lines along the points? – Fruit Mar 20 '13 at 23:54
  • This is quite better approach in my view. Although I would render the `TImage` picture by myself in the `TPaintBox.OnPaint` event and remove that `TImage` component. And, if you want to draw an empty polygon, put the `PaintBox1.Canvas.Brush.Style := bsClear;` line before the call of the `Polygon` function here. [+1] – TLama Mar 21 '13 at 00:19
  • 1
    @TLama I'd prefer the usage of TPaintbox only, too. But possiby Fruit wants to persist the result if all steps done. – bummi Mar 21 '13 at 06:33
2

Make an array of points managed by your form. Declare a dynamic-array field in your form class:

private
  FPoly: array of TPoint;

In your OnClick event, lengthen the array and append a new coordinate to it:

procedure TFruitForm.ImageClick(Sender: TObject);
var
  p: TPoint;
begin
  p := ...;
  SetLength(FPoly, Length(FPoly) + 1);
  FPoly[High(FPoly)] := p;
end;

To assign p, see How do I get the coordinates of the mouse when a control is clicked?

Instead of an array, you might also consider using a generic list: TList<TPoint>.

Community
  • 1
  • 1
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • thanks for the reply, but wouldn't I need the points to be painted on the image aswell? I assigned p := ScreenToClient(p); – Fruit Mar 20 '13 at 22:13
  • Yes, you would need to paint the points, but that's not what your question is about. You asked, "how do I store points in the Array with a onclick event?" You obviously wouldn't want to paint the polygon in the OnClient event, though, because you can't draw the whole polygon until you know all the points. – Rob Kennedy Mar 20 '13 at 22:39
  • yes, store them, and then draw in a button or such...in the mouseclick event when I store the points, wouldn't it be better if I could see where the points are? – Fruit Mar 20 '13 at 22:46
  • Yes, I imagine it would be better. Feel free to write your program that way. – Rob Kennedy Mar 20 '13 at 23:31
  • +1 here to balance my upvote from the other post as this answers [`the question`](http://stackoverflow.com/questions/15534947/draw-polygon-on-image#comment22008734_15534947) while the other post provides the better approach to go. – TLama Mar 21 '13 at 00:27