Помощь - Поиск - Пользователи - Календарь
Полная версия: Кривая Безье
Форум «Всё о Паскале» > Delphi, Assembler и другие языки. > Delphi
Глюк
Здавствуйте,
Подскажите,пожалуйста, алгоритм построения Кривой Безье на Delphi ... smile.gif
volvo
Алгоритм? Рекурсивное деление пополам ... Если ты имеешь в виду метод построения, то существует функция PolyBezier, которая по заданным точкам строит эту самую кривую Безье.
Глюк
Цитата(volvo @ 3.05.2007 18:33) *

Алгоритм? Рекурсивное деление пополам ... Если ты имеешь в виду метод построения, то существует функция PolyBezier, которая по заданным точкам строит эту самую кривую Безье.


А как это.Просто впервые с таким сталкиваюсь...не понимаю,если честно sad.gif
Мне надо шоб точки задавались с помощью мыши (щелчком на области отображения).
volvo
Смотри... На форму брось TImage и TButton, в классе формы опиши:

type
  TForm1 = class(TForm)
  ...
  private
    the_points: array of TPoint;
  ...
end;

и добавь 2 обработчика:

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
const sz=3;
begin
  Image1.Canvas.Pen.Color := clRed;
  Image1.Canvas.Ellipse(X - sz, Y - sz, X + sz, Y + sz);

  setlength(the_points, length(the_points) + 1);
  the_points[length(the_points)-1].X := X;
  the_points[length(the_points)-1].Y := Y;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Image1.Canvas.PolyBezier(the_points);
end;
Теперь щелкни в 4-х местах на Image, этим ты задашь 4 точки. Только внимательно: 2 из них (первая и последняя) - задают начало/конец кривой Безье, а еще 2 - задают ее форму... После того, как 4 точки отмечены - жми кнопку... Вот тебе и кривая...
Глюк
Спасиб,но...Я сделал так,но у меня на TImage точки не ставятся,а в итоге и не рисуется кривая?
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);

  private
    the_points: array of TPoint;

    { Private declarations }
  public
     procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
const sz=3;
begin
  Image1.Canvas.Pen.Color := clRed;
  Image1.Canvas.Ellipse(X - sz, Y - sz, X + sz, Y + sz);

  setlength(the_points, length(the_points) + 1);
  the_points[length(the_points)-1].X := X;
  the_points[length(the_points)-1].Y := Y;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Image1.Canvas.PolyBezier(the_points);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
   close;
end;

end.


Что я не правильно сделал?
volvo
Ты вручную прописывал Image1MouseDown? Так нельзя... убери это и в Object Inspector-е 2 раза щелкни на OnMouseDown для TImage - тогда Дельфи будет знать, что такой обработчик сушествует... Сейчас Дельфи просто не знает о нем, потому как то, что прописано в Private и Public - это твое добавление, а не добавление компилятора...

Попробуй изменить, если не получится - присоединю небольшой работающий проект...
Глюк
Спасибо большое.Теперь рисует smile.gif
Я хотел узнать:а можно сделать так,чтобы задавалось более 4 точек?
volvo
Задавать ты можешь хоть 50, только вот использовать PolyBezier будет только 4 ... Если надо больше - придется отрисовывать вручную...
Глюк
Значит все надо начинать сначала... unsure.gif
Подскажите,пожалуйста,а как можно будет это сделать?
volvo
Почитай вот это (теория про кривые Безье): http://ru.wikipedia.org/wiki/%D0%9A%D1%80%...%B7%D1%8C%D0%B5

А на Арбузе есть неплохая реализация на Паскале: http://forum.arbuz.uz/index.php?showtopic=...indpost&p=13139
Глюк
Ок.Спасибо.
Прога практически готова,тока надо немного подкорректировать...кое-че не то у меня...Ну,думаю,справлюсь
Глюк
Снова я за помощью.Я сделал программку,рисует правильно.Но только почему-то у меня координаты точек смещаются.Что нужно сделать,чтоб рисовалось там,где я кликаю мышкой? unsure.gif


unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Button2: TButton;
    ComboBox1: TComboBox;
    Label1: TLabel;
    Edit2: TEdit;
    Button3: TButton;
    PaintBox2: TPaintBox;
    procedure PaintBox2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  x : array [0..49] of integer;
y : array [0..49] of integer;
implementation

uses ConvUtils;

{$R *.dfm}

procedure TForm1.PaintBox2Click(Sender: TObject);
var p : tpoint;
i,j : integer;
f: string;
begin
i:=strtoint(edit1.Text);
GetCursorPos(p);
x[i]:=p.X;
y[i]:=p.Y;
paintbox2.Canvas.Pen.Color:=clblue;
paintbox2.Canvas.Pen.Width:=5;
paintbox2.Canvas.moveto(p.x,p.y);
paintbox2.Canvas.LineTo(p.x,p.y);
paintbox2.Canvas.TextOut(p.X-2,p.Y-2,'P'+inttostr(i));
i:=i+1;
edit1.text:=inttostr(i);
with paintbox2.Canvas do begin
pen.Color:=clgreen;
pen.Width:=1;
for j:= 0 to i-2 do
begin
moveto(x[j],y[j]);
lineto(x[j+1],y[j+1]);
end;
end;
end;
function fac(q: integer): integer;
var k,s : integer;
begin
      s:=1;
     for k:=1 to q do
     s:=s*k;
     fac:=s;
end;
function step (t:real;i:integer):real;
var k : integer;
s : real;
begin
   s:=1;
   if i=0 then s:=1 else begin
   for k:=1 to i do
   s:=s*t;
   end;
   step:=s;
end;

function vec(n,i : integer): real;
var s : real;
begin
     s:=fac(n)/(fac(i)*fac(n-i));
     vec:=s;
end;
function polin(t:real;n,i:integer):real;
var s:real;
begin
   s:=vec(n,i)*step(t,i)*step(1-t,n-i);
   polin:=s;
end;

function bezex (n : integer; t:real):integer;
var i : integer;
  s : real;
begin
   s:=0;
   for i:=0 to n do
   s:=s+x[i]*polin(t,n,i);
   bezex:=round(s);
end;

function bezey (n : integer; t:real):integer;
var i : integer;
  s : real;
begin
   s:=0;
   for i:=0 to n do
   s:=s+y[i]*polin(t,n,i);
   bezey:=round(s);
end;

procedure TForm1.Button1Click(Sender: TObject);
var t,a,b:real;
  n:integer;
begin
  n:=strtoint(edit1.text)-1;
   t:=0;

   while t<=1 do
   begin
  with paintbox2.Canvas do begin
  pen.Width:=3;
                            pixels[bezex(n,t),bezey(n,t)]:=edit2.color;
                          end;
 t:=t+0.0001;
 end;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
paintbox2.Repaint;
edit1.Text:='0';

end;

procedure TForm1.ComboBox1Change(Sender: TObject);
var s: string;
begin
s:=combobox1.Text;
edit2.color:=StringToColor(s);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
   close;
end;

end.
volvo
Ты считаешь, что глобальные координаты курсора мыши и оконные координаты, в которых должна появиться точка - это одно и то же, а на самом деле это далеко не так... Я не просто так в четвертом посте сделал обработку события OnMouseDown... Смотри:

var
  Form1: TForm1;

  _x : array [0..49] of integer; // Переименовываешь здесь и везде, где имеются в виду массивы
  _y : array [0..49] of integer;


и переносишь обработку нажатия из OnClick в OnMouseDown:
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer); // Здесь - именно оконные координаты клика мыши
var i, j: integer;
begin
  i := strtoint(edit1.Text);
  _x[i]:=X;
  _y[i]:=Y;

  paintbox1.Canvas.Pen.Color:=clblue;
  paintbox1.Canvas.Pen.Width:=5;
  paintbox1.Canvas.moveto(x,y);
  paintbox1.Canvas.LineTo(x,y);
  paintbox1.Canvas.TextOut(X-2,Y-2,'P'+inttostr(i));
  i:=i+1;

  edit1.text:=inttostr(i);
  with paintbox1.Canvas do begin
    pen.Color:=clgreen;
    pen.Width:=1;
    for j:= 0 to i-2 do begin
      moveto(_x[j],_y[j]);
      lineto(_x[j+1],_y[j+1]);
    end;
  end;
end;
Глюк
Спасибо!Я про это и не подумал...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.