Что нового

[Математика] отобразить В-сплайн в графическом редакторе

damien2008

Осваивающий
Сообщения
178
Репутация
34
всем привет. прошу помощи)
в составлении функции для отрисовки В-сплайна по точкам.; я с трудом разобрался в кривых Безье, перечитал половину Википедии, к сожалению спец. мат. образования нет, читаю 'Роджерс Д. - Алгоритмические основы машинной графики', и 'Математические основы -''- ', не получается пока формулы переводить в код.

необходимо по массиву точек, например
Код:
#include <Array.au3>
Local $ArrPoints[7][2]=[[24,  30], _
						[55,  17], _
						[68,  56], _
						[103, 18], _
						[155, 59], _
						[203, 11], _
						[243, 33]]
_ArrayDisplay($ArrPoints)


построить В-сплайн. и как быть, если количество точек меняется динамически?

UPD. нашел функцию для делфи 7 для 6 точек, если есть знающие помогите)
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AppEvnts, ComCtrls;

type
  TForm1 = class(TForm)
    StatusBar1: TStatusBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCanResize(Sender: TObject; var NewWidth,
      NewHeight: Integer; var Resize: Boolean);
  private
    { Private declarations }
  public
    procedure DrawSpline;
  end;

const eps       =5;
      linewidth =3;

var Form1: TForm1;
    P             : array of TPoint;
    m,current,tp  : integer;
    BMP           : TBitmap;

implementation

{$R *.dfm}

procedure TForm1.DrawSpline;
function N0(t:real):real;
begin result:=((1-t)*(1-t)*(1-t))/6; end;
function N1(t:real):real;
begin result:=(3*t*t*t - 6*t*t + 4)/6; end;
function N2(t:real):real;
begin result:=(-3*t*t*t + 3*t*t + 3*t + 1)/6; end;
function N3(t:real):real;
begin result:=(t*t*t)/6; end;

const dt=0.01;
var t   : real;
    x,y : real;
    i   : integer;
begin
  BMP.Canvas.Pen.Color:=clWhite; BMP.Canvas.Brush.Color:=clWhite;
  BMP.Canvas.Rectangle(0,0,bmp.Width,bmp.Height);

  i:=0;
  while ((m-i)>3) do
     begin
     BMP.Canvas.Pen.Width:=1;
     BMP.Canvas.Pen.Color:=clBlack; BMP.Canvas.Brush.Color:=clBlack;
     bmp.Canvas.Ellipse(p[i+0].x-eps,p[i+0].y-eps,p[i+0].x+eps,p[i+0].y+eps);
     bmp.Canvas.Ellipse(p[i+1].x-eps,p[i+1].y-eps,p[i+1].x+eps,p[i+1].y+eps);
     bmp.Canvas.Ellipse(p[i+2].x-eps,p[i+2].y-eps,p[i+2].x+eps,p[i+2].y+eps);
     bmp.Canvas.Ellipse(p[i+3].x-eps,p[i+3].y-eps,p[i+3].x+eps,p[i+3].y+eps);

     bmp.Canvas.MoveTo(p[i+0].x,p[i+0].y);
     bmp.Canvas.LineTo(p[i+1].x,p[i+1].y);
     bmp.Canvas.LineTo(p[i+2].x,p[i+2].y);
     bmp.Canvas.LineTo(p[i+3].x,p[i+3].y);
     bmp.Canvas.LineTo(p[i+1].x,p[i+1].y);

     bmp.Canvas.MoveTo(p[i+0].x,p[i+0].y);
     bmp.Canvas.LineTo(p[i+2].x,p[i+2].y);
     t:=0;
     BMP.Canvas.Pen.Color:=clBlack;
     BMP.Canvas.Pen.Width:=linewidth;
     while t<1 do
        begin
        x:=P[i+0].X*N0(t) + P[i+1].X*N1(t) + P[i+2].X*N2(t) + P[i+3].X*N3(t);
        y:=P[i+0].Y*N0(t) + P[i+1].Y*N1(t) + P[i+2].Y*N2(t) + P[i+3].Y*N3(t);
        if (t=0) then BMP.Canvas.MoveTo(trunc(x),trunc(y)) else
          BMP.Canvas.LineTo(trunc(x),trunc(y));
        t:=t+dt;
        end;
     i:=i+1;
     end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  BMP:=TBitmap.Create;
  BMP.Width:=Form1.ClientWidth;
  BMP.Height:=Form1.ClientHeight;
  m:=6; SetLength(P,m);


  p[0].X:=10;  p[0].Y:=300;
  p[1].X:=50;  p[1].Y:=30;
  p[2].X:=250; p[2].Y:=30;
  p[3].X:=300; p[3].Y:=300;

  p[4].X:=400; p[4].Y:=300;
  p[5].X:=500; p[5].Y:=30;


  DrawSpline;
  current:=-1;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  BMP.Destroy;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  BitBlt(Form1.Canvas.Handle,0,0,Form1.ClientWidth, Form1.ClientHeight,BMP.Canvas.Handle,0,0, SRCCOPY);
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var i:integer;  
begin
  for i:=0 to m-1 do
   if (abs(P[i].X-X)<eps)and(abs(P[i].Y-Y)<eps) then
     begin current:=i; break; end;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if current<0 then exit;
  P[current].x:=x; P[current].y:=y;
  DrawSpline; FormPaint(nil);  
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  current:=-1;
end;

procedure TForm1.FormCanResize(Sender: TObject; var NewWidth,
  NewHeight: Integer; var Resize: Boolean);
begin
  BMP.Width:=NewWidth;
  BMP.Height:=NewHeight;
  DrawSpline; 

end;

end.
 

MnM

Post-Hardcore
Сообщения
679
Репутация
90
В высшей математике я не совсем разбираюсь но нашел ссылку. не знаю поможет или нет(там есть кусочки из какого то ЯП для примеров)
Тут
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Почему именно кривые Безье?
Мне лично кривые Безье не нравятся, потому что они не являются функциональными сплайнами, то есть не проходят через заданные точки.
А какая вообще задача стоит?
 
Автор
damien2008

damien2008

Осваивающий
Сообщения
178
Репутация
34
C2H5OH
задача: по массиву точек составить функцию по отрисовке сплайна (или Б-сплайна, насколько правильно я понял, читая www).
хочу сделать, что-бы он рисовался курсором (это, думаю, сам добавлю), главное составить функцию.

кривая Безье - гугл говорит это частный случай сплайна.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
:scratch:
Задача
по массиву точек составить функцию по отрисовке сплайна
носит чисто академический характер.
В таком случае тебе лучше самому разобраться, потому что задачи академического характера для того и существуют, чтобы, решая их, ты поднимал уровень своих знаний.
 
Верх