Azarien napisał(a)
A czy to ma znaczenie?
Czy musisz mieć wynik identyczny do tego z GIMP-a? To ci da tylko obejrzenie źródeł GIMP-a, jest to program open source.
Zanim ja bym to odkopał w źródłach nie swojego projektu ... , ogólnie metoda z wielomianem jest bardzo niedokładana
wiec raczej odpada.
b0bik napisał(a)
Kiedyś potrzebowałem czegoś podobnego, do rysowania klotoid, ale ostatecznie jakoś chyba zakombinowałem małymi łukami. Co do Twojego problemu, pogooglałem trochę i znalazłem:
http://www.cubic.org/docs/bezier.htm
http://www.efg2.com/Lab/Graphics/Jean-YvesQueinecBezierCurves.htm
http://polymathprogrammer.com/2007/06/27/reverse-engineering-bezier-curves/
http://jsdraw2d.jsfiction.com/demo/curvesbezier.htm
Pzdr
b
Ostatni link działa dokładnie tak jak potrzebuję ( jak znajde chwile zerknę w kod JS)
Przed ostatni link zaimplementowałem w delphi ale funkcja licząca ma dodatkowe parametry U i V i mogę sobie wygenerować nieskończenie wiele krzywych
unit UCurveThroughPoinsts;
interface
{
Stworzone na bazie funkcji drawCurve z projektu:
* Project Name: jsDraw2D (Graphics Library for JavaScript)
* Version: Beta 1.1.0 (17-August-2009) (Uncompressed)
* Project Homepage: http://jsdraw2d.jsfiction.com
* Author: Sameer Burle
* Copyright 2009: jsFiction.com (http://www.jsfiction.com)
* Licensed Under: LGPL
}
uses
Windows, Graphics, dialogs, SysUtils;
type
TArrayOfPoint = array of TPoint;
procedure drawCurve(points_in: TArrayOfPoint; var points_out: TArrayOfPoint; v_Tension: double = 0);
implementation
procedure drawCurve(points_in: TArrayOfPoint; var points_out: TArrayOfPoint; v_Tension: double = 0);
type
T4Points = array[0..3] of TPoint;
var
n: integer;
i: Integer;
phPoints: TArrayOfPoint;
curvePoints: TArrayOfPoint;
v_4points: T4Points;
procedure drawCurveSeg(segPoints: T4Points ; tension: double; var p_nowe_punkty: TArrayOfPoint);
var
x,y: Integer;
xd,yd: Double;
xl, yl: Integer;
k,f,t: Double;
m1x: Double;
m2x: Double;
m1y: Double;
m2y: Double;
begin
x:=0;
y:=0;
xl:=segPoints[1].x-1;
yl:=segPoints[1].y-1;
t:=0;
f:=1;
k:=1.1;
m1x:=(1-tension)*(segPoints[2].x-segPoints[0].x)/2;
m2x:=(1-tension)*(segPoints[3].x-segPoints[1].x)/2;
m1y:=(1-tension)*(segPoints[2].y-segPoints[0].y)/2;
m2y:=(1-tension)*(segPoints[3].y-segPoints[1].y)/2;
while(t<=1) do
begin
x:=0;
y:=0;
xd:= (2*t*t*t-3*t*t+1)*segPoints[1].x + (t*t*t-2*t*t+t)*m1x + (-2*t*t*t+3*t*t)*segPoints[2].x + (t*t*t-t*t)*m2x;
yd:= (2*t*t*t-3*t*t+1)*segPoints[1].y + (t*t*t-2*t*t+t)*m1y + (-2*t*t*t+3*t*t)*segPoints[2].y + (t*t*t-t*t)*m2y;
x:=round(xd);
y:=round(yd);
if (x<>xl) OR (y<>yl) then
begin
if(x-xl>1) OR (y-yl>1) OR (xl-x>1) OR (yl-y>1) then
begin
t:= t-f;
f:=f/k;
end
else
begin
// ??curvePoints[curvePoints.length]=new jsPoint(x,y);
SetLength(p_nowe_punkty, High(p_nowe_punkty)+2 );
p_nowe_punkty[High(p_nowe_punkty)].X := x;
p_nowe_punkty[High(p_nowe_punkty)].Y := y;
xl:=x;
yl:=y;
if(t+f>1) then
t:=1-f;
end
end
else
begin
f:=f*k;
end;
t:= t+f;
end;
end;
begin
SetLength(phPoints, High(points_in) - Low(points_in) +1 );
// ja tylko kopiuje w orginale było kasowanie duplikatów @TO DO!!!
for I := Low(points_in) to High(points_in) do
begin
phPoints[i] := points_in[i];
end;
// jak by jakies punkty wyleciały wczesniej trzeba by to poprawić
// ma być o jeden mniej niż dlugosc tablicy z punktami
n := High(phPoints) - Low(phPoints) ;//+ 1;
for i:=0 to n-1 do
begin
if i=0 then
begin
v_4points[0] := phPoints[0];
v_4points[1] := phPoints[0];
v_4points[2] := phPoints[1];
v_4points[3] := phPoints[2];
drawCurveSeg( v_4points, v_Tension, curvePoints )
end
else
if i=n-1 then
begin
v_4points[0] := phPoints[n-2];
v_4points[1] := phPoints[n-1];
v_4points[2] := phPoints[n];
v_4points[3] := phPoints[n];
drawCurveSeg( v_4points, v_Tension, curvePoints )
end
else
begin
v_4points[0] := phPoints[i-1];
v_4points[1] := phPoints[i];
v_4points[2] := phPoints[i+1];
v_4points[3] := phPoints[i+2];
drawCurveSeg( v_4points, v_Tension, curvePoints )
end;
end;
points_out := curvePoints;
end;
end.
Jak tego użyć:
procedure TForm33.btn3Click(Sender: TObject);
var
points_in: TArrayOfPoint;
points_out: TArrayOfPoint;
v_Tension: double;
I: integer;
begin
SetLength(points_in,4);
points_in[0].X := 0;
points_in[0].Y := 0;
points_in[1].X := 32;
points_in[1].Y := 200;
points_in[2].X := 185;
points_in[2].Y := 34;
points_in[3].X := 255;
points_in[3].Y := 255;
drawCurve(points_in, points_out, v_Tension);
for I := Low(points_out) to High( points_out ) do
begin
Canvas.Pixels[points_out[i].X, points_out[i].Y] := clRed;
end;
end;