Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
|
[pasca] offtopic: народ ! кто сам писал алгоритм ... 11.05.01 16:22 Число просмотров: 825
Автор: Dr.Golova Статус: Незарегистрированный пользователь
|
> Нужен исходник по сплайнам , т.е. проведение гладкой кривой > через несколько точек на плоскости ... > Хорошо бы на C++ ... Но разберусь и в инородных > исходниках... > Идею ухватить просто пока не смог ...
program Spline_Draw;
uses crt, graph;
type TPoint = record
X, Y : Real;
end;
const NP = 5;
Res = 50;
var PMas : array [-1..NP+2] of TPoint;
GrDrv, GrMod : Integer;
MaxX, MaxY : Integer;
i, j : Integer;
c : Char;
procedure MakePolinom (C1,C2,C3,C4 : TPoint; T,D : Real; var X,Y : Real);
var T2, T3 : Real;
begin
T2 := Sqr(T);
T3 := T2 * T;
X := ( C1.X*T3 + C2.X*T2 + C3.X*T + C4.X ) / D;
Y := ( C1.Y*T3 + C2.Y*T2 + C3.Y*T + C4.Y ) / D;
end;
procedure CalcBSpline(N : Integer; var C1,C2,C3,C4 : TPoint);
begin
C1.X := -PMas[N-1].X + 3*PMas[N].X -3*PMas[N+1].X + PMas[N+2].X;
C2.X := 3*PMas[N-1].X -6*PMas[N].X + 3*PMas[N+1].X { + 0*PMas[N+2].X};
C3.X := -3*PMas[N-1].X { + 0*PMas[N].X} + 3*PMas[N+1].X { + 0*PMas[N+2].X};
C4.X := PMas[N-1].X + 4*PMas[N].X + PMas[N+1].X { + 0*PMas[N+2].X};
C1.Y := -PMas[N-1].Y + 3*PMas[N].Y -3*PMas[N+1].Y + PMas[N+2].Y;
C2.Y := 3*PMas[N-1].Y -6*PMas[N].Y + 3*PMas[N+1].Y { + 0*PMas[N+2].Y};
C3.Y := -3*PMas[N-1].Y { + 0*PMas[N].Y} + 3*PMas[N+1].Y { + 0*PMas[N+2].Y};
C4.Y := PMas[N-1].Y + 4*PMas[N].Y + PMas[N+1].Y { + 0*PMas[N+2].Y};
end;
procedure CalcCatmullSpline(N : Integer; var C1,C2,C3,C4 : TPoint);
begin
C1.X := -PMas[N-1].X + 3*PMas[N].X - 3*PMas[N+1].X + PMas[N+2].X;
C2.X := 2*PMas[N-1].X - 5*PMas[N].X + 4*PMas[N+1].X - PMas[N+2].X;
C3.X := -PMas[N-1].X { + 0*PMas[N].X } + PMas[N+1].X { + 0*PMas[N+2].X };
C4.X := { 0*PMas[N-1].X } 2*PMas[N].X { + 0*PMas[N+1].X + 0*PMas[N+2].X};
C1.Y := -PMas[N-1].Y + 3*PMas[N].Y - 3*PMas[N+1].Y + PMas[N+2].Y;
C2.Y := 2*PMas[N-1].Y - 5*PMas[N].Y + 4*PMas[N+1].Y - PMas[N+2].Y;
C3.Y := -PMas[N-1].Y { + 0*PMas[N].Y } + PMas[N+1].Y { + 0*PMas[N+2].Y };
C4.Y := { 0*PMas[N-1].Y } 2*PMas[N].Y { + 0*PMas[N+1].Y + 0*PMas[N+2].Y};
end;
procedure DrawBSpline(N, Resolution : Integer);
var i, j : Integer;
X1, Y1, X2, Y2 : Real;
C1, C2, C3, C4 : TPoint;
begin
PMas[-1] := PMas[1];
PMas[0] := PMas[1];
PMas[N+1] := PMas[N];
PMas[N+2] := PMas[N];
for i := 0 to N do
begin
CalcBSpline(i, C1, C2, C3, C4);
MakePolinom(C1, C2, C3, C4, 0, 6, X2, Y2);
for j := 1 to Resolution do
begin
MakePolinom(C1, C2, C3, C4, j/Resolution, 6, X1, Y1);
Line(Round(X2), Round(Y2), Round(X1), Round(Y1));
X2 := X1; Y2 := Y1;
end;
end;
end;
procedure DrawCatmullSpline(N, Resolution : Integer);
var i, j : Integer;
X1, Y1, X2, Y2 : Real;
C1, C2, C3, C4 : TPoint;
begin
PMas[0] := PMas[1];
PMas[N+1] := PMas[N];
for i := 1 to N-1 do
begin
CalcCatmullSpline(i, C1, C2, C3, C4);
MakePolinom(C1, C2, C3, C4, 0, 2, X2, Y2);
for j := 1 to Resolution do
begin
MakePolinom(C1, C2, C3, C4, j/Resolution, 2, X1, Y1);
Line(Round(X1), Round(Y1), Round(X2), Round(Y2));
X2 := X1; Y2 := Y1;
end;
end;
end;
procedure DrawX;
var i : Integer;
begin
for i := 1 to NP do
begin
Line(Round(PMas[i].X-3), Round(PMas[i].Y),
Round(PMas[i].X+3), Round(PMas[i].Y));
Line(Round(PMas[i].X), Round(PMas[i].Y-3),
Round(PMas[i].X), Round(PMas[i].Y+3));
end;
end;
{============================================================================}
begin
Randomize;
GrDrv := Detect;
InitGraph(GrDrv, GrMod, ''); { }
if GraphResult <> GrOk then
begin
Writeln(#10#13, 'Error initializing graphics !');
Writeln('egavga.bgi must be in current dir !', #10#13);
Halt(0);
end;
MaxX := GetMaxX; MaxY := GetMaxY;
repeat
for i := 1 to NP do
begin
PMas[i].X := Random(MaxX);
PMas[i].Y := Random(MaxY);
end;
SetColor(LightRed);
DrawCatmullSpline(NP, Res);
SetColor(LightGreen);
DrawBSpline(NP, Res);
SetColor(Yellow);
DrawX;
c := ReadKey;
ClearDevice;
until c = Chr(27);
CloseGraph; { }
end.
|
<programming>
|
Offtopic: народ ! кто сам писал алгоритм ... 11.05.01 14:38
Автор: Shadow Walker Статус: Незарегистрированный пользователь
|
Нужен исходник по сплайнам , т.е. проведение гладкой кривой через несколько точек на плоскости ...
Хорошо бы на C++ ... Но разберусь и в инородных исходниках...
Идею ухватить просто пока не смог ...
|
|
[pasca] offtopic: народ ! кто сам писал алгоритм ... 11.05.01 16:22
Автор: Dr.Golova Статус: Незарегистрированный пользователь
|
> Нужен исходник по сплайнам , т.е. проведение гладкой кривой > через несколько точек на плоскости ... > Хорошо бы на C++ ... Но разберусь и в инородных > исходниках... > Идею ухватить просто пока не смог ...
program Spline_Draw;
uses crt, graph;
type TPoint = record
X, Y : Real;
end;
const NP = 5;
Res = 50;
var PMas : array [-1..NP+2] of TPoint;
GrDrv, GrMod : Integer;
MaxX, MaxY : Integer;
i, j : Integer;
c : Char;
procedure MakePolinom (C1,C2,C3,C4 : TPoint; T,D : Real; var X,Y : Real);
var T2, T3 : Real;
begin
T2 := Sqr(T);
T3 := T2 * T;
X := ( C1.X*T3 + C2.X*T2 + C3.X*T + C4.X ) / D;
Y := ( C1.Y*T3 + C2.Y*T2 + C3.Y*T + C4.Y ) / D;
end;
procedure CalcBSpline(N : Integer; var C1,C2,C3,C4 : TPoint);
begin
C1.X := -PMas[N-1].X + 3*PMas[N].X -3*PMas[N+1].X + PMas[N+2].X;
C2.X := 3*PMas[N-1].X -6*PMas[N].X + 3*PMas[N+1].X { + 0*PMas[N+2].X};
C3.X := -3*PMas[N-1].X { + 0*PMas[N].X} + 3*PMas[N+1].X { + 0*PMas[N+2].X};
C4.X := PMas[N-1].X + 4*PMas[N].X + PMas[N+1].X { + 0*PMas[N+2].X};
C1.Y := -PMas[N-1].Y + 3*PMas[N].Y -3*PMas[N+1].Y + PMas[N+2].Y;
C2.Y := 3*PMas[N-1].Y -6*PMas[N].Y + 3*PMas[N+1].Y { + 0*PMas[N+2].Y};
C3.Y := -3*PMas[N-1].Y { + 0*PMas[N].Y} + 3*PMas[N+1].Y { + 0*PMas[N+2].Y};
C4.Y := PMas[N-1].Y + 4*PMas[N].Y + PMas[N+1].Y { + 0*PMas[N+2].Y};
end;
procedure CalcCatmullSpline(N : Integer; var C1,C2,C3,C4 : TPoint);
begin
C1.X := -PMas[N-1].X + 3*PMas[N].X - 3*PMas[N+1].X + PMas[N+2].X;
C2.X := 2*PMas[N-1].X - 5*PMas[N].X + 4*PMas[N+1].X - PMas[N+2].X;
C3.X := -PMas[N-1].X { + 0*PMas[N].X } + PMas[N+1].X { + 0*PMas[N+2].X };
C4.X := { 0*PMas[N-1].X } 2*PMas[N].X { + 0*PMas[N+1].X + 0*PMas[N+2].X};
C1.Y := -PMas[N-1].Y + 3*PMas[N].Y - 3*PMas[N+1].Y + PMas[N+2].Y;
C2.Y := 2*PMas[N-1].Y - 5*PMas[N].Y + 4*PMas[N+1].Y - PMas[N+2].Y;
C3.Y := -PMas[N-1].Y { + 0*PMas[N].Y } + PMas[N+1].Y { + 0*PMas[N+2].Y };
C4.Y := { 0*PMas[N-1].Y } 2*PMas[N].Y { + 0*PMas[N+1].Y + 0*PMas[N+2].Y};
end;
procedure DrawBSpline(N, Resolution : Integer);
var i, j : Integer;
X1, Y1, X2, Y2 : Real;
C1, C2, C3, C4 : TPoint;
begin
PMas[-1] := PMas[1];
PMas[0] := PMas[1];
PMas[N+1] := PMas[N];
PMas[N+2] := PMas[N];
for i := 0 to N do
begin
CalcBSpline(i, C1, C2, C3, C4);
MakePolinom(C1, C2, C3, C4, 0, 6, X2, Y2);
for j := 1 to Resolution do
begin
MakePolinom(C1, C2, C3, C4, j/Resolution, 6, X1, Y1);
Line(Round(X2), Round(Y2), Round(X1), Round(Y1));
X2 := X1; Y2 := Y1;
end;
end;
end;
procedure DrawCatmullSpline(N, Resolution : Integer);
var i, j : Integer;
X1, Y1, X2, Y2 : Real;
C1, C2, C3, C4 : TPoint;
begin
PMas[0] := PMas[1];
PMas[N+1] := PMas[N];
for i := 1 to N-1 do
begin
CalcCatmullSpline(i, C1, C2, C3, C4);
MakePolinom(C1, C2, C3, C4, 0, 2, X2, Y2);
for j := 1 to Resolution do
begin
MakePolinom(C1, C2, C3, C4, j/Resolution, 2, X1, Y1);
Line(Round(X1), Round(Y1), Round(X2), Round(Y2));
X2 := X1; Y2 := Y1;
end;
end;
end;
procedure DrawX;
var i : Integer;
begin
for i := 1 to NP do
begin
Line(Round(PMas[i].X-3), Round(PMas[i].Y),
Round(PMas[i].X+3), Round(PMas[i].Y));
Line(Round(PMas[i].X), Round(PMas[i].Y-3),
Round(PMas[i].X), Round(PMas[i].Y+3));
end;
end;
{============================================================================}
begin
Randomize;
GrDrv := Detect;
InitGraph(GrDrv, GrMod, ''); { }
if GraphResult <> GrOk then
begin
Writeln(#10#13, 'Error initializing graphics !');
Writeln('egavga.bgi must be in current dir !', #10#13);
Halt(0);
end;
MaxX := GetMaxX; MaxY := GetMaxY;
repeat
for i := 1 to NP do
begin
PMas[i].X := Random(MaxX);
PMas[i].Y := Random(MaxY);
end;
SetColor(LightRed);
DrawCatmullSpline(NP, Res);
SetColor(LightGreen);
DrawBSpline(NP, Res);
SetColor(Yellow);
DrawX;
c := ReadKey;
ClearDevice;
until c = Chr(27);
CloseGraph; { }
end.
|
|
Offtopic: народ ! кто сам писал алгоритм ... 11.05.01 16:06
Автор: Тореро Статус: Незарегистрированный пользователь
|
Могу на Delphi скинуть
|
|
совет 11.05.01 16:04
Автор: jcukeng Статус: Незарегистрированный пользователь
|
> Нужен исходник по сплайнам , т.е. проведение гладкой кривой > через несколько точек на плоскости ... > Идею ухватить просто пока не смог ... возьми учебник по численным методам и прочитай пару страниц.
еще есть неплохая книга по сплайнам, автор Шикин.
идея сплайнов примитивная до безобразия. разберешься за полчаса.
удачи!
йцукенг
|
| |
Спасибо , разобрался ... Действительно все просто ... Да и в С++ встроенная фишка есть - PolyBezier... 12.05.01 12:59
Автор: Shadow Walker Статус: Незарегистрированный пользователь
|
Спасибо , разобрался ... Действительно все просто ...
Да и в С++ встроенная фишка есть - PolyBezier ...
|
| | |
[C++] Не так все просто 13.05.01 08:07
Автор: Zef <Alloo Zef> Статус: Elderman
|
Я 2 года бьюсь, пока не добился. Задача такая: как провести через произвольное количество точек кривую, непрерывную или из кусочков, с заданием касательных на входе и выходе, главное, чтобы была плавной и без выбросов. Полином Лагранжа не подходит - он дает непредсказуемые выбросы, кроме того у него нельзя задать касательные. Безье - то же, тут другой геморрой: как задать направляющие вектора? Примитивные решения, типа равны по модулю, смотрят в разные стороны и параллельны прямой, соединяющей 2 соседние точки дают весма непрезентабельный результат. Из всего, что я видел, самый лучший сплайн строит Автокад, но кто знает, какой алгоритм он использует?
|
| | | |
[C++] Не так все просто 15.05.01 22:04
Автор: Paskal Статус: Незарегистрированный пользователь
|
Да всё не сложно, просто не надо путать полиномы со сплайнами. Для соответствующего сплайна не сложно задать и условия на концах.
> Я 2 года бьюсь, пока не добился. Задача такая: как провести > через произвольное количество точек кривую, непрерывную или > из кусочков, с заданием касательных на входе и выходе, > главное, чтобы была плавной и без выбросов. Полином > Лагранжа не подходит - он дает непредсказуемые выбросы, > кроме того у него нельзя задать касательные. Безье - то же, > тут другой геморрой: как задать направляющие вектора? > Примитивные решения, типа равны по модулю, смотрят в разные > стороны и параллельны прямой, соединяющей 2 соседние точки > дают весма непрезентабельный результат. Из всего, что я > видел, самый лучший сплайн строит Автокад, но кто знает, > какой алгоритм он использует?
|
| | | |
[C++] Точно ... 14.05.01 13:39
Автор: Shadow Walker Статус: Незарегистрированный пользователь
|
Я сначала полиномами аппроксимировать пытался , но там например точки , расположенные по кругу нельзя ....
Безье - там ввообще гладкая кривая только для 4 точек ...
Так что ищу пока способ. Ведь делают же.
Основная идея для меня - алгоритм проведения гладкой кривой через множество точек, неизвестно как расположенных ( раскиданных по плоскости ). Пример - ключевые точки , задающие дорогу на карте. Дорога идет как ей угодно (возможно пересекаясь сама с собой) ... Надо провести гладкую кривую ...
Пока не знаю как ...
|
| | | | |
Численные методы ... они самые... 16.05.01 02:07
Автор: Torq Статус: Незарегистрированный пользователь
|
Вообще говоря сплайн строится кубический и по четырём точкам, только все сплайны в промежуточных точках склеивают условием совпадения касательной, а условия на краях выбирают произвольно или наклаюывают условие естественности. Получается достаточно гладкая кривая, проходяшая через все точки. Условия сшития рассчитываются прогонкой.
|
|
|