Вот и дошли мы до нелинейной динамики, мир которой поражает настолько, что просто заставляет написать простую программу для того, чтобы понаблюдать за каким-нибудь объектом с интересным хаотическим поведением.
Проще всего изобразить аттрактор Лоренца, который получается из простой системы дифференциальных уравнений при начальных условиях:
float x = 3.051522, y = 1.582542, z = 15.62388;
А собственно система уравнений:
x = tx + 5 * (ty - tx) * di; y = ty + (15 * tx - ty - tz * tx) * di; z = tz + (-tz + tx * ty) * di; где tx, ty, tz - временные копии переменных x, y, z
Итоговый код приложения:
import dgui.all; // отрисовка отдельных точек void drawPoint(Canvas c, int x, int y) { Pen p = new Pen(SystemColors.darkGreen, 1, PenStyle.solid); c.drawLine(p, x, y, x + 1, y + 1); }; // аттрактор Лоренца void drawAttractor(Canvas c) { float x = 3.051522, y = 1.582542, z = 15.62388; float tx, ty, tz; float di = 0.001; for (float i = 0; i < 100; i += di) { tx = x; ty = y; tz = z; x = tx + 5 * (ty - tx) * di; y = ty + (15 * tx - ty - tz * tx) * di; z = tz + (-tz + tx * ty) * di; auto eX = (4.8 * x) / z; auto eY = (-2.5 * y) / z; auto X = cast(int) (250 - 50 * eX); auto Y = cast(int) (250 - 50 * eY); drawPoint(c, X, Y); } } class MainForm : Form { public this() { this.text = "Аттрактор Лоренца"; this.size = Size(500, 550); this.startPosition = FormStartPosition.centerScreen; }; protected override void onPaint(PaintEventArgs e) { Canvas c = e.canvas; drawAttractor(c); super.onPaint(e); } }; int main(string[] args) { return Application.run(new MainForm()); }
Немного пояснений: eX и eY — это переменные для отображения результата построения в псевдо-3D, определенные преобразования с подобранными на «глаз» коэффициентами. В принципе, программа будет неплохо работать и без них.
И результат: