Задать вопрос
@EvgenyApMr

Почему не строится график?

Есть задача: построить по массиву точек график, а после по этим точкам построить кривую Безье.
Есть рабочий пример на C#:
using System;
using System.Drawing;
using System.Windows.Forms;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Graphics G; // Объект графики
        PointF[] Arr = new PointF[] // Исходный массив точек
        {
            new PointF(10,150),
            new PointF(5,50),
            new PointF(150,50),
            new PointF(140,140),
            new PointF(150,50),
            new PointF(150,50),
            new PointF(150,50),
 
        };
        int Fuctorial(int n) // Функция вычисления факториала
        {
            int res = 1;
            for (int i = 1; i <= n; i++)
                res *= i;
            return res;
        }
        float polinom (int i, int n, float t)// Функция вычисления полинома Бернштейна
            {
            return (Fuctorial(n)/(Fuctorial(i) * Fuctorial(n - i)))* (float)Math.Pow(t, i) * (float)Math.Pow(1 - t, n - i);
            }
        void Draw()// Функция рисования кривой
        {
            int j = 0;
            float step = 0.01f;// Возьмем шаг 0.01 для большей точности
 
            PointF[] result = new PointF[101];//Конечный массив точек кривой
            for (float t = 0; t < 1; t += step)
            {
                float ytmp = 0;
                float xtmp = 0;
                for (int i = 0; i < Arr.Length; i++)
                { // проходим по каждой точке
                    float b = polinom(i, Arr.Length - 1, t); // вычисляем наш полином Бернштейна
                    xtmp += Arr[i].X * b; // записываем и прибавляем результат
                    ytmp += Arr[i].Y * b;
                }
                result[j] = new PointF(xtmp, ytmp);
                j++;
 
            }
            G.DrawLines(new Pen(Color.Red), result);// Рисуем полученную кривую Безье
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            G = Graphics.FromHwnd(pictureBox1.Handle);
            G.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            Draw();
        }
    }
}

637f4c0a50da8189019447.jpeg

Я пытаюсь изобразить то же самое на delphi, но результат получается совершенно не такой.
Код:
var
  x,y: array[1..7] of real;
  i: byte;

function factorial(n:real):real; //Считаем факториал
    begin
        if n <= 1 then
          begin
            Result := 1;
          end
        else
          begin
            Result := n * factorial(n - 1);
          end;
    end;

function getBezierBasis(i, n, t:real):real; //Считаем полином
    begin
	    Result := (factorial(n)/(factorial(i)*factorial(n - i)))* Power(t, i)* Power(1 - t, n - i);
    end;

procedure TForm1.Button1Click(Sender: TObject); //Рисуем график по массиву точек
    begin

        x[1]:= 10;
        x[2]:= 5;
        x[3]:= 150;
        x[4]:= 140;
        x[5]:= 150;
        x[6]:= 150;
        x[7]:= 150;

        y[1]:= 150;
        y[2]:= 50;
        y[3]:= 50;
        y[4]:= 140;
        y[5]:= 50;
        y[6]:= 50;
        y[7]:= 50;

        for i:=1 to Length(x) do
            begin
                Chart1.Series[0].addxy(x[i],y[i]);
            end;
    end;

procedure TForm1.Button2Click(Sender: TObject); //Рисуем кривую Безье
    var
        f: byte;
        a, t, xt,yt, gbb: real;

    begin
        a:=0;

    While a <> 100 do
        begin
            a:=a+1;
                for i := 1 to Length(x) do
                begin
                    gbb:= getBezierBasis(i, Length(x), a/100); //Делим индекс a на 100 для получения диапазона подстановки от 0 до 1 
                    xt := x[i]*gbb;
                    yt := y[i]*gbb;
                    chart1.SeriesList[1].AddXY(xt, yt);
                end;
        end;
    end;
end.


637f4c8b1b32c467896169.png
  • Вопрос задан
  • 260 просмотров
Подписаться 1 Простой 12 комментариев
Решения вопроса 1
HemulGM
@HemulGM Куратор тега Delphi
Delphi Developer, сис. админ
код
uses Math, System.Types;

procedure TForm4.FormCreate(Sender: TObject);
begin
  Arr := [
    TPointF.Create(10, 150),
    TPointF.Create(5, 50),
    TPointF.Create(150, 50),
    TPointF.Create(140, 140),
    TPointF.Create(150, 50),
    TPointF.Create(150, 50),
    TPointF.Create(150, 50)
    ];
end;

function TForm4.Fuctorial(n: Integer): Integer; // Функция вычисления факториала
begin
  var res := 1;
  for var i := 1 to n do
    res := res * i;
  Result := res;
end;

function TForm4.polinom(i, n: integer; t: Single): Single; // Функция вычисления полинома Бернштейна
begin
  Result := (Fuctorial(n) / (Fuctorial(i) * Fuctorial(n - i))) * Math.Power(t, i) * Math.Power(1 - t, n - i);
end;

procedure TForm4.Draw();// Функция рисования кривой
begin
  var j := 0;
  var step := 0.01; // Возьмем шаг 0.01 для большей точности

  var res: TArray<TPoint>;
  SetLength(res, 101); //Конечный массив точек кривой

  var t: Single := 0;
  while t < 1 do
  begin
    t := t + step;
    var ytmp := 0.0;
    var xtmp := 0.0;
    for var i := 0 to High(Arr) do
    begin // проходим по каждой точке
      var b := polinom(i, Length(Arr) - 1, t); // вычисляем наш полином Бернштейна
      xtmp := xtmp + Arr[i].X * b; // записываем и прибавляем результат
      ytmp := ytmp + Arr[i].Y * b;
    end;
    res[j] := TPoint.Create(Round(xtmp), Round(ytmp));
    Inc(j);
  end;

  for var i := 0 to High(res) - 1 do
  begin
    Canvas.MoveTo(res[i].X, res[i].Y);
    Canvas.LineTo(res[i + 1].X, res[i + 1].Y); // Рисуем полученную кривую Безье
  end;
end;

procedure TForm4.FormPaint(Sender: TObject);
begin
  Draw;
end;


637f97cd8d0c7133132952.png

стандартный проект vcl со сглаживанием (меняется только процедура Draw())

uses Direct2D, Winapi.D2D1;

procedure TForm4.Draw();// Функция рисования кривой
begin
  var j := 0;
  var step := 0.01; // Возьмем шаг 0.01 для большей точности

  var res: TArray<TD2DPoint2f>;
  SetLength(res, 101); //Конечный массив точек кривой

  var t: Single := 0;
  while t < 1 do
  begin
    t := t + step;
    var ytmp := 0.0;
    var xtmp := 0.0;
    for var i := 0 to High(Arr) do
    begin // проходим по каждой точке
      var b := polinom(i, Length(Arr) - 1, t); // вычисляем наш полином Бернштейна
      xtmp := xtmp + Arr[i].X * b; // записываем и прибавляем результат
      ytmp := ytmp + Arr[i].Y * b;
    end;
    res[j].x := xtmp;
    res[j].y := ytmp;
    Inc(j);
  end;
  with TDirect2DCanvas.Create(Canvas, ClientRect) do
  try
    BeginDraw;
    for var i := 0 to High(res) - 1 do
      DrawLine(res[i], res[i+1]);
    EndDraw;
  finally
    Free;
  end;
end;



637f9ce29d069377716122.png

вот на FMX со сглаживанием (меняется только немного процедура Draw()
код

procedure TForm4.Draw();// Функция рисования кривой
begin
  var j := 0;
  var step := 0.01; // Возьмем шаг 0.01 для большей точности

  var res: TArray<TPointF>;
  SetLength(res, 101); //Конечный массив точек кривой

  var t: Single := 0;
  while t < 1 do
  begin
    t := t + step;
    var ytmp := 0.0;
    var xtmp := 0.0;
    for var i := 0 to High(Arr) do
    begin // проходим по каждой точке
      var b := polinom(i, Length(Arr) - 1, t); // вычисляем наш полином Бернштейна
      xtmp := xtmp + Arr[i].X * b; // записываем и прибавляем результат
      ytmp := ytmp + Arr[i].Y * b;
    end;
    res[j] := TPointF.Create(xtmp, ytmp);
    Inc(j);
  end;
  Canvas.BeginScene;
  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Color := TAlphaColorRec.Red;
  for var i := 0 to High(res) - 1 do
  begin
    Canvas.DrawLine(res[i], res[i+1], 1); // Рисуем полученную кривую Безье
  end;
  Canvas.EndScene;
end;


637f99ead5c4a101937108.png
под андроид
637f9b25c8d6a912753313.jpeg
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы