Советы по Delphi


*** Рисование КРИВЫХ в Delphi? ***


Решение 1

Автор: dmitrys@phyast.la.asu.edu (Dmitry Streblechenko)

В: У кого-нибудь есть исходный код или какая-либо информация для рисования кривых Безье? Я должен использовать их в своем компоненте. Пожалуйста используйте для ответа мой адрес электронной почты.

О: Я делал это недавно; мне было лениво разбираться с тем, как рисовать кривые Безье с помощью Win API, поэтому я использовал функцию Polyline().

Примечание: для координатных точек я использовал реальные величины типа floating (я применял некоторый тип виртуального экрана), округляя их до целого.

    PBezierPoint = ^TBezierPoint; TBezierPoint = record X,Y:double;   //основной узел

Xl,Yl:double; //левая контрольная точка Xr,Yr:double; //правая контрольная точка end;
//P1 и P2 - две точки TBezierPoint, расположенные между 0 и 1:
//когда t=0 X=P1.X, Y=P1.Y; когда t=1 X=P2.X, Y=P2.Y;

procedure BezierValue(P1,P2:TBezierPoint; t:double; var X,Y:double);
var t_sq,t_cb,r1,r2,r3,r4:double; begin t_sq := t * t; t_cb := t * t_sq; r1 := (1 - 3*t + 3*t_sq -   t_cb)*P1.X; r2 := (    3*t - 6*t_sq + 3*t_cb)*P1.Xr; r3 := (          3*t_sq - 3*t_cb)*P2.Xl; r4 := (                     t_cb)*P2.X; X  := r1 + r2 + r3 + r4; r1 := (1 - 3*t + 3*t_sq -   t_cb)*P1.Y; r2 := (    3*t - 6*t_sq + 3*t_cb)*P1.Yr; r3 := (          3*t_sq - 3*t_cb)*P2.Yl; r4 := (                     t_cb)*P2.Y; Y  := r1 + r2 + r3 + r4; end;

Для рисования кривой Безье разделяем интервал между P1 и P2 на несколько отрезков (их количество влияет на точность воспроизведения кривой, 3 - 4 точки вполне достаточно), затем в цикле создаем массив точек, используем описанную выше процедуру с параметром t от 0 до 1 и рисуем данный массив точек, используя функцию polyline().

Решение 2

В: У кого-нибудь есть исходный код или какая-либо информация для рисования кривых Безье? Я должен использовать их в своем компоненте. Пожалуйста используйте для ответа мой адрес электронной почты.

Я решил ответить на этот крик души - причина?: 1. Не первый раз вижу подобный вопрос, 2. Задача настолько избита, что я без труда нашел ответ в своем архиве. (BTW: У меня есть более старые решения, чем это ;-P)

Тем не менее эта технология жива до сих пор и приносит свои плоды:

    (********************************************************************)
(*                         GRAPHIX TOOLBOX 4.0                      *)
(*       Copyright (c) 1985, 87 by  Borland International, Inc.     *)
(********************************************************************)
unit GShell;

interface

{------------------------------ вырезано --------------------------}

procedure Bezier(A : PlotArray; MaxContrPoints : integer;
var B : PlotArray; MaxIntPoints : integer);
implementation

{------------------------------ вырезано --------------------------}

procedure Bezier{(A : PlotArray; MaxContrPoints : integer;
var B : PlotArray; MaxIntPoints : integer)}; const
MaxControlPoints = 25; type
CombiArray = array[0..MaxControlPoints] of Float; var
N : integer; ContrPoint, IntPoint : integer; T, SumX, SumY, Prod, DeltaT, Quot : Float; Combi : CombiArray;
begin
MaxContrPoints := MaxContrPoints - 1; DeltaT := 1.0 / (MaxIntPoints - 1); Combi[0] := 1; Combi[MaxContrPoints] := 1; for N := 0 to MaxContrPoints - 2 do Combi[N + 1] := Combi[N] * (MaxContrPoints - N) / (N + 1); for IntPoint := 1 to MaxIntPoints do begin T := (IntPoint - 1) * DeltaT; if T <= 0.5 then begin Prod := 1.0 - T; Quot := Prod; for N := 1 to MaxContrPoints - 1 do Prod := Prod * Quot; Quot := T / Quot; SumX := A[MaxContrPoints + 1, 1]; SumY := A[MaxContrPoints + 1, 2]; for N := MaxContrPoints downto 1 do begin SumX := Combi[N - 1] * A[N, 1] + Quot * SumX; SumY := Combi[N - 1] * A[N, 2] + Quot * SumY; end; end else begin Prod := T; Quot := Prod; for N := 1 to MaxContrPoints - 1 do Prod := Prod * Quot; Quot := (1 - T) / Quot; SumX := A[1, 1]; SumY := A[1, 2]; for N := 1 to MaxContrPoints do begin SumX := Combi[N] * A[N + 1, 1] + Quot * SumX; SumY := Combi[N] * A[N + 1, 2] + Quot * SumY; end; end; B[IntPoint, 1] := SumX * Prod; B[IntPoint, 2] := SumY * Prod; end; end; { Bezier }

end. { GShell }

[000110]



Содержание раздела