I'm making a program that will draw a Serpenksiy's Triangle on a Decart and Polar coordinate system. I thought that using Polygon()
will be perfect for that, but for some reason it does not draw a triangle, it draws a line. I do not understand why, and I can't come up with an answer.
Here is the code:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TGraphForm = class(TForm)
img1: TImage;
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
GraphForm: TGraphForm;
implementation
uses
Unit1;
{$R *.dfm}
procedure TGraphForm.FormActivate(Sender: TObject);
var
Ax, Ay, Bx, By, Cx, Cy: integer;
x0, y0 :integer;
begin
//взятие параметров Defining Points of Triangle
Ax := StrToInt(MainForm.EditAx.Text);
Ay := StrToInt(MainForm.EditAy.Text);
Bx := StrToInt(MainForm.EditBx.Text);
By := StrToInt(MainForm.EditBx.Text);
Cx := StrToInt(MainForm.EditCx.Text);
Cy := StrToInt(MainForm.EditCx.Text);
//0 функции Center of system (0;0)
x0 := img1.Width div 2;
y0 := img1.Height div 2;
//Оси Drawing Axis
with img1.Canvas do
begin
MoveTo(x0,0);
LineTo(x0, ClientHeight);
MoveTo(0, y0);
LineTo(ClientWidth, y0);
end;
//график
//главный треугольник
with img1.Canvas do
begin
Polygon ([Point(-Ax x0,-Ay y0), Point(-Bx x0,-By y0), Point(-Cx x0,-Cy y0)]);
end;
end;
end.
CodePudding user response:
So, with help from Remy Lebeau (the great man) i fixed the problem. Actually, i have no clue how, but now it works. Here is the changed code:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, System.Types;
type
TGraphForm = class(TForm)
img: TImage;
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
GraphForm: TGraphForm;
implementation
uses
Unit1;
{$R *.dfm}
procedure TGraphForm.FormActivate(Sender: TObject);
var
// переменные Variables
Ax, Ay, Bx, By, Cx, Cy: integer;
x0, y0 :integer;
scale :integer;
begin
// координаты вершин Points of triangle
Ax := StrToInt(MainForm.EditAx.Text)*-1;
Ay := StrToInt(MainForm.EditAy.Text)*-1;
Bx := StrToInt(MainForm.EditBx.Text)*-1;
By := StrToInt(MainForm.EditBy.Text)*-1;
Cx := StrToInt(MainForm.EditCx.Text)*-1;
Cy := StrToInt(MainForm.EditCy.Text)*-1;
// точка пересечения осей Where is the zero
x0 := img.Width div 2;
y0 := img.Height div 2;
// множитель масштабирования scale multiplier
scale :=-40;
with img.Canvas do
begin
//рисование осей drawing Axises
MoveTo(x0, 0);
LineTo(x0, img.Height);
MoveTo(0, y0);
LineTo(img.Width, y0);
//Making poligon (triangle)
Brush.Color := clBlack;
Polygon( [Point(Ax*scale x0, Ay*-scale y0), Point(Bx*scale x0, By*-scale y0), Point(Cx*scale x0, Cy*-scale y0)] );
end;
end;
end.
CodePudding user response:
From the comments on the OP's answer, it is clear that the OP doesn't fully understand the concepts involved. To help the OP, I'd like to answer him/her in the comments thread, but due to technical limitations (comment length, formatting, etc.), I am unable to.
Therefore I write this "pseudoanswer" for the benefit of the OP. When the OP has read this answer, I may delete it.
Create a new VCL application. Then add the following OnPaint
handler:
procedure TForm1.FormPaint(Sender: TObject);
begin
// Clear background
Canvas.Brush.Color := clWhite;
Canvas.FillRect(ClientRect);
// Draw a circle
Canvas.Brush.Color := clNavy;
var P := ClientRect.CenterPoint;
Canvas.Ellipse(P.X - 20, P.Y - 20, P.X 20, P.Y 20);
end;
The OnPaint
handler is called every time the form needs to redraw itself.
Please note that I first clear the background; otherwise we'll end up with more and more circles as the form is repainted.
Now, we also want to redraw the form every time it is resized. To this end, add a OnResize
handler:
procedure TForm1.FormResize(Sender: TObject);
begin
Invalidate;
end;
To further illustrate the principle, let's animate the ball so it bounces in a simulated field of gravity. To this end, add private instance variables to the form:
private
x, y, // position
vx, vy, // velocity
ax, ay: Double; // acceleration
and in the OnCreate
handler, give them initial values:
procedure TForm1.FormCreate(Sender: TObject);
begin
x := ClientWidth / 2;
y := ClientHeight / 2;
vx := 1000;
vy := 1000;
ax := 0;
ay := 6000;
end;
Then add a TTimer
to the form, set its Interval
to 30
and give it the following OnTimer
event handler:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
const dt = 0.01;
vx := vx ax * dt;
vy := vy ay * dt;
x := x vx * dt;
y := y vy * dt;
if x < 0 then
begin
vx := -0.9*vx;
x := 1;
end;
if x > ClientWidth then
begin
vx := -0.9*vx;
x := ClientWidth - 1;
end;
if y < 0 then
begin
vy := -0.9*vy;
y := 1;
end;
if y > ClientHeight then
begin
vy := -0.9*vy;
y := ClientHeight - 1;
end;
Invalidate;
end;
and change the OnPaint
handler to
procedure TForm1.FormPaint(Sender: TObject);
begin
// Clear background
Canvas.Brush.Color := clWhite;
Canvas.FillRect(ClientRect);
// Draw a circle
Canvas.Brush.Color := clNavy;
var CentrePoint := Point(Round(x), Round(y));
const R = 10;
Canvas.Ellipse(CentrePoint.X - R, CentrePoint.Y - R, CentrePoint.X R, CentrePoint.Y R);
end;
You may notice some flickering. To get rid of this, the standard trick is to add a
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
message handler to your form class:
procedure TForm1.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
Message.Result := 1;
end;
For extra fun, add the following OnClick
handler:
procedure TForm1.FormClick(Sender: TObject);
begin
vx := 5000 * (Random 0.5);
vy := 5000 * (Random 0.5);
end;