Have done this code so fare ( http://paste.php.lv/2670/nonum ) whanna know how can I draw line in 360 not only 45 ? If it is possible some1 plz tell or show how can I do that. Thanks.
This forum is intended for the FIRST Robotics Competition, the particular team is sponsored by the Delphi company. It has no affiliation with the Delphi programming language.
Sticky explaining this more
More information on FIRST Robotics
Google search for Delphi help
Don’t lock it yet…I might be able to assist him, despite the fact that he’s come to the wrong place.
Sorry if I had posted my problem in wrong forum But I hope u can help me with my problem.
Here’s some modified code. First of all, you should be indenting and spacing your code consistently, so that it’s easier to read and understand. Unfortunately, the code tags for vBulletin don’t handle the spaces and tabs elegantly, so bear with this.
unit Unit1;
{$O-}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Button1: TButton;
procedure FormClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
procedure linija(x1,y1,x2,y2:integer);
implementation
{$R *.dfm}
procedure linija(x1, y1, x2, y2: integer);
var
dx, dy, p, x, y, xend, xt: integer;
begin
dx := abs(x1 - x2);
dy := abs(y2 - y1);
p := 2 * dx - dx; //Why? This equals p := dx;
if x1 > x2
then
begin
x := x2;
y := y2;
xend := x1;
end
else
begin
x := x1;
y := y1;
xend := x2;
end;
for xt := x to xend do
begin
if p < 0
then
p := p + 2 * dy
else
begin
y := y + 1; //You don't draw the first y-point!
p := p + 2 * (dy - dx);
end;
form1.Canvas.Pixels[xt, y] := clBlack; //Use the constant's name
end;
end;
procedure TForm1.FormClick(Sender: TObject);
begin
linija(100, 100, mouse.CursorPos.X, mouse.CursorPos.Y);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
linija(strtoint(edit1.Text), strtoint(edit2.Text), strtoint(edit3.Text), strtoint(edit4.Text));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := IntToStr(Form1.ClientWidth div 2);
Edit2.Text := IntToStr(Form1.ClientHeight div 2);
Edit3.Text := '0';
Edit4.Text := '0';
end;
end.
Now, as for what’s wrong, I’m not going to rewrite this for you, because it looks suspiciously like an assignment. But take a look at the conditions for x and xend as it goes through the for xt… loop. If I take (250, 250) and (250, 0) as my co-ordinates, x = xend, so the loop will just execute once (at xt := x) and stop because xt = xend. In fact, you’re using x-values as a counter, and then changing the size of each y-segment. But you only ever increment y by one, so the height of each y-segment is always 1. You’re not even using p, which seems designed to serve this purpose (note that p >= 0 for all cases, except if (dy < 0) and (2 * dy > p) or ((dy - dx) < 0) and (2 * (dy - dx) > p), so I think your logic there might be a little messed up). This is rather hard to explain, but take a look at the attached file, which shows lines at (what your program thinks are) (250, 250)->(250, 0),(250, 250)->(250, 10), (250, 250)->(250, 20), (250, 250)->(250, 30) & (250, 250)->(250, 40). Obviously, those aren’t the lines being drawn; instead, y always goes up by 1, and x is incremented by 1 (due to the for loop). So you get 45° lines.
Further, by setting y := y + 1 at every iteration of the loop, before drawing the pixel, you’re actually offsetting your line by (0, 1). Re-arrange the loop so that the first value of y is y1, not y1 + 1.
Try figuring out some logic which says:
- Find x and y distances.
- For each x, how much does y grow (i.e. y = f(x) = mx + b, where m is a slope, and b a starting co-ordinate)?
- If m = ∞, do a special case for a vertical line.
- Otherwise, since m = ∆y / ∆x, evaluate m as (y2 - y1) div (x2 - x1), and make a segment of straight line (using a for loop) from either (x, y)->(x, y + m) or (x, y)->(x + 1 div m, y), depending on the slope (either greater or less than 45°).
- Repeat for each y or x, depending on whether you increment x by 1 div m, or y by m, respectively.
Edit: I just realized that you don’t want to do 1 div ((y2 - y1) div (x2 - x1)), because of roundoff concerns (you’re eliminating the remainder twice!). Do instead mInverse := (x2 - x1) div (y2 - y1) for that case.
Also, it might be helpful to look up TCanvas.LineTo and TCanvas.MoveTo in the help files. Unless you need to write the code yourself, I think that these already do what you need. Call Form1.Canvas.MoveTo(x1, y1), then call Form1.Canvas.LineTo(x2, y2). With any luck, you’ll get a line, without fighting with it.
Finally, I haven’t rigourously checked this, so I’m not sure if I’m right. But I think it might be of some benefit…
Thanks a lot I will try, I readet your replay and I understand what u are talking about, so tnx very much. :o
You’re actually doing too much work, assuming that you don’t need to show (your own) code for actually generating the line; Delphi allows you to just do this:
Form1.Canvas.MoveTo(x1, y1);
Form1.Canvas.LineTo(x2, y2);
Which is actually the only important part of this:
unit Unit1;
{$O-} //Directive to turn off optimization of variables, for debugging only
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Memo1: TMemo;
ColorDialog1: TColorDialog;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var
Form1: TForm1;
function DrawLine(x1, y1, x2, y2: Integer): Boolean;
implementation
{$R *.dfm}
function DrawLine(x1, y1, x2, y2: Integer): Boolean;
begin
if (x1 <= Form1.ClientWidth) AND (x1 >= 0) AND //Checking boundaries
(x1 <= Form1.ClientWidth) AND (x2 >= 0) AND //(not strictly
(y2 <= Form1.ClientHeight) AND (y1 >= 0) AND //necessary, but often
(y2 <= Form1.ClientHeight) AND (y2 >= 0) //a good idea)
then
begin
Form1.Canvas.MoveTo(x1, y1); //These two lines are all
Form1.Canvas.LineTo(x2, y2); //you really need
Result := True;
end
else
Result := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if DrawLine(StrToInt(Edit1.Text), StrToInt(Edit2.Text), StrToInt(Edit3.Text),
StrToInt(Edit4.Text))
then
Memo1.Text := Concat('(', Edit1.Text, ', ', Edit2.Text, '), (',
Edit3.Text, ', ', Edit4.Text, ')')
else
Memo1.Text := 'Line out of bounds';
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if ColorDialog1.Execute then Canvas.Pen.Color := ColorDialog1.Color;
end;
end.
This code also includes definitions for the functions, range checking, and (as extra stuff) a colour picker dialog (as an example of how to use the built-in functions) and a little feedback for the status of the line. See the attachments for what it looks like. The colour picker is on the controls toolbar under “Dialogs”—drop it on the form like a button to use it.
With Delphi, as with most other “visual” languages, a lot of code is devoted to defining the controls on the form. Also, some code is devoted to error-checking, not because it’s strictly needed, but because good coding style dictates that you reject out-of-range values (unless you know exactly what they will do).
I’ll leave it to you to implement the program by choosing what you want to do with the code above (because it’s not exactly what you asked for), but it’s really just a matter of placing the appropriate controls on the form, and taking a good look at the help files regarding the properties of each control that you use.
Also, remember that this is just the shortcut method that I’ve demonstrated; the algorithm you were working on earlier is probably pretty similar to what the LineTo() procedure implements, except that the source code for LineTo() is hidden in the gdi32.dll file, somewhere where you can’t see it. If you’re assigned the task “draw a line in Delphi”, LineTo() will work. If you’re assigned the task “implement an algorithm to draw a line in Delphi”, you should continue with the algorithm you were developing earlier, because in that case, the real assignment is the creation of the logic, not the line itself.