Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как лучше нарисовать параболу по трём точкам? 
V
    Опции темы
KPEHDEL
Дата 25.5.2013, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Здравствуйте.
Делаю программу для численного интегрирования. Есть Методы левых, правых? центральных, прямоугольников, трапеций и симпсона.

Вот с последним проблема. С другими вроде всё достаточно понятно. Пример:
Левых прямоугольников: http://s2.ipicture.ru/uploads/20130525/GpjkpRRG.png
Трапеций: http://s2.ipicture.ru/uploads/20130525/n6xoS2nq.png


Проблема и вопрос в том, как лучше нарисовать/визуализировать метод Симпсона(Парабол).

Использую компонент Chart.
На данный момент метод выглядит примерно так:
Код

procedure TForm1.simpson;
var
  i:integer;
begin
  I_simpson:=0;
  SeriesSimpson.Clear;
  if N mod 2 <> 0 then
    EditSimpson.Text:=trim(EditN.text)+'%2!=0'
  else
    begin
      for i:=0 to N-1 do  // Проходим по всем разбиениям
        begin
          i_simpson:=i_simpson + ((points[i].xR- points[i].xL)*(funcs[i].fL+4*funcs[i].fM+funcs[i].fR))/6;  // Считаю.
          SeriesSimpson.AddXY(points[i].xL, funcs[i].fL); // Рисую.
          //Здесь наверное создавать вложенный цикл и в нём добавлять на график(в пределах разбиения) точки по какому-то принципу.
        end;
      SeriesSimpson.AddXY(points[N].xL, funcs[N].fL);
      EditSimpson.Text:=floattostrf(i_simpson, ffGeneral, 4, 8);
      SeriesSimpson.Active:=false;
    end;
end;


Если для визуализации предыдущих методов достаточно было двух точек, то здесь точек для визуализации надо больше и располагать их внутри отрезка.

Собственно сам вопрос. 
Как через 3 точки нарисовать параболу?
Допустим, для каждого разделения будет вложенный цикл. По какому принципу(формуле) между этими 3 точками добавить и рассчитать их координаты, чтобы получилась парабола?

Визуально должно выглядеть примерно так:
http://en.academic.ru/pictures/enwiki/83/S...llustration.png
http://s2.ipicture.ru/uploads/20130525/pCJ32P0J.png
http://s2.ipicture.ru/uploads/20130525/izJsVNfR.png


С нетерпением жду ответа.
Заранее спасибо.

Это сообщение отредактировал(а) KPEHDEL - 25.5.2013, 13:09
PM MAIL WWW ICQ   Вверх
Beltar
Дата 25.5.2013, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 3
Всего: 7



Если я правильно понял, то http://ru.wikipedia.org/wiki/Парабола
Последний раздел, вычисление коэффицинтов по трем точкам, после чего построение графика y(x) становится тривиальным.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Фантом
Дата 25.5.2013, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



По определению метода Симпсона, на каждом отрезке интегрирования функция интерполируется параболой, проходящей через точки функции с аргументами, равными крайним и средней точкам отрезка. Следовательно, если есть отрезок [x1,x3] и средняя точка x2=(x1+x3)/2, а также значения функции y1=f(x1) и т.д., то у Вас есть система уравнений вида:
a*x1^2+b*x1+c=y1
a*x2^2+b*x2+c=y2
a*x3^2+b*x3+c=y3

Она решается относительно a,b,c, тем самым Вы получаете выражения для коэффициентов параболы, которую на этом участке надо нарисовать.

PM   Вверх
KPEHDEL
  Дата 25.5.2013, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Спасибо за ответы.
Что-то я совсем запутался... Помогите осознать, что делаю не так...

Результат получился такой:
http://s2.ipicture.ru/uploads/20130525/fE4RP54Z.png

Что даже немного не похоже не правду. Что-то я не так делаю с f(x).

Код

procedure TForm1.simpson;
var
  i,j:integer;
  x1,x2,x3:real;
  y,y1,y2,y3:real;
  a,b,c:real;

begin
  I_simpson:=0;
  SeriesSimpson.Clear;
  if N mod 2 <> 0 then
    EditSimpson.Text:=trim(EditN.text)+'%2!=0'
  else
    begin
      for i:=0 to N-1 do  // Проходим по всем разбиениям
        begin
          i_simpson:=i_simpson + ((points[i].xR- points[i].xL)*(funcs[i].fL+4*funcs[i].fM+funcs[i].fR))/6;  // Считаю.
          SeriesSimpson.AddXY(points[i].xL, funcs[i].fL); // Рисую.

          x1 := points[i].xL;
          x3 := points[i].xR;
          x2 := ( x1 + x3 ) / 2;
          //Здесь наверное создавать вложенный цикл и в нём добавляем точки для рисования параболы.
          for j:=1 to 10 do
          begin
            y1 := Fx(x1+j/10);
            y3 := Fx(x3+j/10);
            y2 := ( y1 + y3 ) / 2;

            a := ( y3 - ( x3 * ( y2 - y1 ) + x2 * y1 - x1 * y2 ) / ( x2 - x1 ) ) / ( x3 * ( x3 - x1 - x2 ) + x1 * x2 );
            b := ( ( y2 - y1 ) / ( x2 - x1 ) ) - a*( x1 + x2 );
            c := ( ( x2*y1 - x1*y2 ) / x2 - x1 ) + a*x1*x2;
            y := a*(x1*x1) + b*x1 + c;
            SeriesSimpson.AddXY( points[i].xL + j / 10, y );
          end;
        end;
      SeriesSimpson.AddXY(points[N].xL, funcs[N].fL);
      EditSimpson.Text:=floattostrf(i_simpson, ffGeneral, 4, 8);
      SeriesSimpson.Active:=false;
    end;
end;


Это сообщение отредактировал(а) KPEHDEL - 25.5.2013, 18:12
PM MAIL WWW ICQ   Вверх
KPEHDEL
Дата 25.5.2013, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Есть прогресс.
f(x) = sin(x): http://s2.ipicture.ru/uploads/20130525/mTX3NE1K.png
f(x) = x: http://s2.ipicture.ru/uploads/20130525/01C5cQhu.png

На интервале 8 разбиений, но так как вертикальные черты прорисовываются и от точек для параболы, выглядит будто их много.

Собственно 2 вопроса:
1. Это ведь не верно? Будь верно, на f(x) = x, мы бы увидели не сходимость, а искривления параболы? Или я что-то не понимаю?
2. Как убрать вертикальные черты от точек для параболы, которые задаются во вложенном цикле на каждом отрезке разбиения?

Если не верно, подскажите в чём и я продолжу разбираться. Код ниже.

Код:
Код

procedure TForm1.simpson;
var
  i,j:integer;
  x1,x2,x3:real;
  x,y,y1,y2,y3:real;
  a,b,c:real;

begin
  I_simpson:=0;
  SeriesSimpson.Clear;
  if N mod 2 <> 0 then
    EditSimpson.Text:=trim(EditN.text)+'%2!=0'
  else
    begin
      for i:=0 to N-1 do  // Проходим по всем разбиениям
        begin
          i_simpson:=i_simpson + ((points[i].xR- points[i].xL)*(funcs[i].fL+4*funcs[i].fM+funcs[i].fR))/6;  // Считаю.
          SeriesSimpson.AddXY(points[i].xL, funcs[i].fL); // Рисую.

          x := points[i].xL;
          x1 := points[i].xL;
          x3 := points[i].xR;
          x2 := ( x1 + x3 ) / 2;

          y1 := funcs[i].fL;
          y3 := funcs[i].fR;
          y2 := ( y1 + y3 ) / 2;

          //Здесь наверное создавать вложенный цикл и в нём добавляем точки для рисования параболы.
          while x < x3 do
          begin
            a := ( y3 - ( x3 * ( y2 - y1 ) + x2 * y1 - x1 * y2 ) / ( x2 - x1 ) ) / ( x3 * ( x3 - x1 - x2 ) + x1 * x2 );
            b := ( ( y2 - y1 ) / ( x2 - x1 ) ) - a*( x1 + x2 );
            c := ( ( x2*y1 - x1*y2 ) / x2 - x1 ) + a*x1*x2;
            x := x+0.25;
            y := a*sqr(x) + b*x + c;
            SeriesSimpson.AddXY( x, Fx(x) );
          end;
        end;
      SeriesSimpson.AddXY(points[N].xL, funcs[N].fL);
      EditSimpson.Text:=floattostrf(i_simpson, ffGeneral, 4, 8);
      SeriesSimpson.Active:=false;
    end;
end;



С нетерпением жду ответа.

Это сообщение отредактировал(а) KPEHDEL - 25.5.2013, 20:55
PM MAIL WWW ICQ   Вверх
Фантом
Дата 25.5.2013, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



Цитата(KPEHDEL @  25.5.2013,  21:45 Найти цитируемый пост)

1. Это ведь не верно? Будь верно, на f(x) = x, мы бы увидели не сходимость, а искривления параболы? Или я что-то не понимаю?

Прямая - частный случай параболы, так что все нормально. Коэффициент a у Вас везде в этом случае получается равным 0 (проверьте, если не лень), как и должно быть.

Цитата(KPEHDEL @  25.5.2013,  21:45 Найти цитируемый пост)
2. Как убрать вертикальные черты от точек для параболы, которые задаются во вложенном цикле на каждом отрезке разбиения?

Ну, тут Вам виднее, как Вы их рисуете...
PM   Вверх
Beltar
Дата 25.5.2013, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 3
Всего: 7



Код

 a := ( y3 - ( x3 * ( y2 - y1 ) + x2 * y1 - x1 * y2 ) / ( x2 - x1 ) ) / ( x3 * ( x3 - x1 - x2 ) + x1 * x2 );
            b := ( ( y2 - y1 ) / ( x2 - x1 ) ) - a*( x1 + x2 );
            c := ( ( x2*y1 - x1*y2 ) / x2 - x1 ) + a*x1*x2;
            y := a*(x1*x1) + b*x1 + c;


1) Вычисления a, b, c из цикла выносятся.
2) Ты зачем в ф-ию подстваляешь x1, когда надо ее просто протабулировать от x1 до x2?


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
KPEHDEL
Дата 25.5.2013, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Beltar,
Цитата

1) Вычисления a, b, c из цикла выносятся.

Да, вынес.

Цитата

2) Ты зачем в ф-ию подстваляешь x1, когда надо ее просто протабулировать от x1 до x2? 


Ну в последнем варианте кода я так и делаю:
Цитата

x := x+0.25;
y := a*sqr(x) + b*x + c;
SeriesSimpson.AddXY( x, Fx(x) );


Если это верно. То проблема решена, всем спасибо smile 

Ну и если кто-то знает как убрать вертикальные разделительные линии, которые появляются при использовании метода AddXY(x,y) для создания точки, буду благодарен...(Как не отображать известно, а вот как управлять отображением нужных из кода хз) А то что-то не могу найти. Быть может для этого надо использовать другой метод добавления точки?

Это сообщение отредактировал(а) KPEHDEL - 25.5.2013, 23:09
PM MAIL WWW ICQ   Вверх
KPEHDEL
  Дата 26.5.2013, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Блин, я обнаружил ошибку... Всё не верно...
В коде выше, в этом куске:
Код

while x < x3 do
          begin
            a := ( y3 - ( x3 * ( y2 - y1 ) + x2 * y1 - x1 * y2 ) / ( x2 - x1 ) ) / ( x3 * ( x3 - x1 - x2 ) + x1 * x2 );
            b := ( ( y2 - y1 ) / ( x2 - x1 ) ) - a*( x1 + x2 );
            c := ( ( x2*y1 - x1*y2 ) / x2 - x1 ) + a*x1*x2;
            x := x+0.25;
            y := a*sqr(x) + b*x + c;
            SeriesSimpson.AddXY( x, Fx(x) );
          end;


При добавлении точки, подставляю Fx(x). Тем самым я просто рисую текущую функцию smile 
Вычисленный y, нигде не используется... А должен подставлять y. Если подставлю y, то на графике полная белиберда.

Подскажите пожалуйста где ошибка и как правильно записать?

Это сообщение отредактировал(а) KPEHDEL - 26.5.2013, 15:45
PM MAIL WWW ICQ   Вверх
KPEHDEL
Дата 26.5.2013, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Нашёл одну ошибку.
Она заключалась в вычислении  коэффициента C.
Код

// c := ( ( x2*y1 - x1*y2 ) / x2 - x1 ) + a*x1*x2; // так было
c := (x2*y1 - x1*y2) / (x2-x1) + a*x1*x2; // так нужно


Однако есть где-то ещё ошибка, график всё ещё не верен. 
http://s2.ipicture.ru/uploads/20130528/Ypl6X4PA.jpg

К сообщению прикрепил архив с исходниками, возможно так будет проще найти ошибку.



Это сообщение отредактировал(а) KPEHDEL - 28.5.2013, 07:32

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  Программа_для_интегрирования.zip 575,86 Kb
PM MAIL WWW ICQ   Вверх
KPEHDEL
  Дата 28.5.2013, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



По мимо ошибки в вычислении коэффициента C.

Нашёл ещё одну ошибку. Зачем-то я на каждом отрезке интервала в X присваивал 0.
Теперь это выглядит так:
http://s1.ipicture.ru/uploads/20130528/UaOit895.png

Но это тоже не верно, не параболы( Помогите найти остальные ошибки.

Добавлено @ 09:44
Кажется я понял.

Фантом
Я глупец, повёлся и не подумал)
Не x2=(x1+x3)/2, а x2=(x3-x1)/2  smile И соответственно y2=(y3-y1)/2

И того получается:
на 8 узлах: http://s2.ipicture.ru/uploads/20130528/84eLj7gB.jpg

На 2 узлах: http://s2.ipicture.ru/uploads/20130528/8QLTO0xM.jpg

Но это ведь тоже не верно? Ведь Симпсон должен быть точнее, а на графике он что-то совсем не точен...

Это сообщение отредактировал(а) KPEHDEL - 28.5.2013, 10:00
PM MAIL WWW ICQ   Вверх
Фантом
Дата 28.5.2013, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



Цитата(KPEHDEL @  28.5.2013,  10:29 Найти цитируемый пост)

Я глупец, повёлся и не подумал)
Не x2=(x1+x3)/2, а x2=(x3-x1)/2  smile И соответственно y2=(y3-y1)/2

Это Вы как-то неудачно подумали.  smile Если сдвиг переменной не используется (а исходно предполагалось именно это), то там должна быть сумма.
PM   Вверх
KPEHDEL
  Дата 28.5.2013, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Фантом, беда. Тогда я в конец запутался.
Если делаю 
x2=(x1+x3)/2, y2=(y1+y3) получается на графике вот что:
http://s1.ipicture.ru/uploads/20130528/4rMVCW6d.jpg
А это на Симпсона не похоже, скорее на трапеций.

Текущие исходники прикрепил к сообщению.

В чём может быть дело?


Это сообщение отредактировал(а) KPEHDEL - 28.5.2013, 10:30

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  Программа_для_интегрирования.zip 575,80 Kb
PM MAIL WWW ICQ   Вверх
KPEHDEL
Дата 28.5.2013, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Кажется я понял почему так получается. 
При: x2=(x1+x3)/2, y2=(y1+y3) 
У нас получается, что средняя точка. точна по середине. И того, все 3 точки расположены на прямой.
У Параболы такого быть не может.

Всё верно? Если да, то как быть? Как правильно посчитать третью точку?)

Кажется мне надо смотреть в сторону кривой Безье.



Это сообщение отредактировал(а) KPEHDEL - 28.5.2013, 18:34
PM MAIL WWW ICQ   Вверх
Фантом
Дата 29.5.2013, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



Цитата(KPEHDEL @  28.5.2013,  19:13 Найти цитируемый пост)
При: x2=(x1+x3)/2, y2=(y1+y3) 

Откуда? y_i=f(x_i), расположены на одной прямой все три точки будут только в том случае, если Вы интегрируете линейную функцию (чего явно не наблюдается).

По-видимому, в этом и ошибка. x3 можно и нужно считать как среднее значение концов интервала x1 и x2, но к значениям функции это совершенно не относится.
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0975 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.