krzywa przez 4 punkty

0

Jak narysować taką krzywą jak na obrazku:
http://w643.wrzuta.pl/obraz/8ccLjn7Ks1f/krzywe

Mamy współrzędne 4 punktów przez które krzywa ma przechodzić.

Eksperymentowałem tak:
var
points: array [1..4] of TPoint;

Canvas.PolyBezier(points);

Nie zadziała jednak bo punkty 2 i 3 są poza krzywą
(węzły kontrolne) a nie są punktami na krzywej.

Problem pewnie polega na znalezieniu takich punktów dla funkcji PolyBezier
aby krzywa przechodziła przez te punkty co ja chcę

M

1

Dziękuje za odpowiedz, ale chyba nie dokładnie to jest to czego szukam
bo sadząc po wynikach to szukanie wielomianu który przechodzi przez te punkty które oczekuje daje inne wyniki niż to widac w GIMP

Na tej stronie co podałeś był program do testowania
Wynik wyglada tak:
http://w131.wrzuta.pl/obraz/3rF5M9pQpCu/wykres2

Dane wejściowe:
P1 (0;0);
P2 (35;155);
P3 (115;101);
P4 (255;255);
Takie dane były dla gimpa
na tym wykresie
http://w643.wrzuta.pl/obraz/8ccLjn7Ks1f/krzywe

Wydaje mi się że to jednak będzie bezier , tylko trzeba wiedzieć jak go opisać aby przeszedł przez te 4 punkty

1

kiedys mialem ten sam problem ale w koncu zrezygnowalem bo nie bylo mi to az tak potrzebne.
zerknij na osatni post i daj znac jesli Ci sie uda:
canvas.bezier() jak zrobic zeby przechodzila przez punky?

1

Nawet nie wiem o co zapytac google :(

1

cimak - dziękuje za dobry przykład idealny do zabawy jeżeli chodzi o rysowanie krzywych
teraz ponad wszelką wątpliwość jestem pewny że że to nie może być jedna krzywa bezier tylko co najmniej dwie (albo więcej )

0

No to już mam konto
Niestety login Adamek było zajęte :(

1

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.

1

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

0
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;

1 użytkowników online, w tym zalogowanych: 0, gości: 1