Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

Спасибо за реализацию, она действительно быстрая. Но не все линии отрисовывает в нужную сторону... Необходимо добавить проверку для случая X-линии if(y1 "<" y0) grad=-grad; и аналогично для Y-линии if(x1 "<" x0) grad=-grad; P.S. На...
Отличные уроки(учу GL по ним), только в renderScene нужно добавить очистку буфера цвета и буфера глубины. При изменении размеров треугольники размножаются)
как исправить это , сделал все по инструкции
Timer1 - выдает ошибку. Использовал IdleTimer1, работает! unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, OpenGLContext, GL, GLU; type { TForm1 } TForm1 =...
в коде присутствуют ошибки! // Считываем координаты procedure TForm1.getCoords(Sender: TObject); var j1:longint; begin n:= StrToInt(Edit2.Text); //число точек s1:=Edit1.Text; s2:=''; i := 1; j:=1; k:=0...

Счетчики и рейтинг

Яндекс.Метрика Рейтинг@Mail.ru
Скриншот к примеру
Среда программирования: 
Microsoft Visual Studio 2013
Статья по теме: 

Для определённого количества точек, заданных своими координатами, построить кривую, называемую β-сплайном, которая является аппроксимацией неизвестной функции, содержащей исходные точки.
Создаём форму с полем для рисования графика, кнопками "Рассчитать", "Добавить", "Удалить" (вершину) и панелью, состоящей из полей для ввода координат.
В поля вводим целые числа в необходимом порядке, если нужно, добавляем новые поля или удаляем неиспользуемые. Для построения графика нажимаем кнопку "Рассчитать".
Основные компоненты программы:

  • Структура mypanel, состоящая из панели с полями для ввода;
  • Массив исходных (опорных) точек coords, в который передаются данные из полей ввода;
  • Функции
    1. 1)load_Form (загрузка формы),
    2. 2)new_Panel (создание новой панели),
    3. 3)Coefficient (расчёт коэффициентов),
    4. 4)Draw_spline (построение сплайна),
    5. 5)Calculate (перенос данных с панелей в массив и вызов функций рисования).
Код программы: 

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
 
namespace b_spline
{
    public partial class Form1 : Form
    {
        public struct mypanel // создаём структуру, содержащую 
        {
            //панель, на которой расположены
            public Panel pan;
            //два поля для ввода координат
            public TextBox tbxx;
            public TextBox tbxy;
            //  и надписи X и Y.
            public Label lx;
            public Label ly;
        }
        public mypanel temp; //с помощью этой переменной будем инициализировать новые панели
        private List<mypanel> pnls;// список панелей, в котором будут храниться все наши панели
        public int pnls_num;// количество элементов в списке
        public PointF[] coords; // массив точек, в который будем загружать записанные в текстбоксы данные из списка панелей
        private float[] a = new float[4];// массив для рассчёта коэффициентов а
        private float[] b = new float[4];// для рассчёта коэффициентов b
        public Graphics graph;// поверхность для рисования
        public Bitmap btmp;// рисунок
        public Pen axis_pen = new Pen(Color.Black, 1);//  для рисования осей
        public Pen spline_pen = new Pen(Color.Blue, 1); //  для рисования сплайна
        public SolidBrush points_brush= new SolidBrush(Color.Red); // для рисования опорных точек
        public Form1()
        {
            this.InitializeComponent();
        }
        private void load_Form(object sender, EventArgs e)
        {
            load();
        }// обработка события " загрузка формы"
        public void load()
        {
            temp = new mypanel();// создаем новый объект типа mypanel, из которого будем передавать данные в список
            // инициализируем уже  существующими элементами (для удобства построения
            temp.pan = panel12;
            temp.tbxx = TextBox23;
            temp.tbxy = TextBox24;
            temp.lx = label23;
            temp.ly = label24;
            pnls = new List<mypanel>(4);// инициализируем список панелей (минимум 4 точки)
            pnls.Add(temp);// добавляем существующую панель в список
            for (int i = 1; i < 4; i++)
                pnls.Add(new_Panel(pnls[i - 1])); //создаём еще 3 панели 
            pnls_num = 4;// устанавливаем счётчик
        }
        public void Add_to_control(mypanel panel)
        {
            // добавляем родителей каждому элементу структуры. Это необходимо для отображения на экране
            flowLayoutPanel1.Controls.Add(panel.pan);
            panel.pan.Controls.Add(panel.tbxx);
            panel.pan.Controls.Add(panel.tbxy);
            panel.pan.Controls.Add(panel.lx);
            panel.pan.Controls.Add(panel.ly);
        }
        public mypanel new_Panel(mypanel sender)
        {
            //инициализируем объект mypanel и объекты, которые к нему подсоединим
            temp = new mypanel();
            temp.pan = new Panel();// панель, содержащая боксы и надписи
            temp.lx = new Label();
            temp.ly = new Label();
            temp.tbxx = new TextBox();// бокс для ввода x
            temp.tbxy = new TextBox();// бокс для ввода y
            temp.pan.Location = new Point(3, 28*sender.pan.Location.Y + 3);// каждую новую панель сдвигаем на 28 пикселов вниз
            temp.pan.Name = "panel" + temp.pan.Location.Y;// имя
            temp.pan.Size = new Size(152, 25);// размер
            temp.lx.Font = temp.ly.Font = new Font("Times New Roman", 6.75F, FontStyle.Bold, GraphicsUnit.Point, 204);//параметры шрифта
            temp.lx.Margin = temp.ly.Margin = new Padding(0);//внешняя граница не видна
            temp.lx.Size = temp.ly.Size = new Size(14, 11);// размер
            temp.lx.Text = "X:";// текст в label'ах
            temp.ly.Text = "Y:";
            //координаты label lx и ly
            temp.lx.Location = new Point(1, 7);//координаты
            temp.ly.Location = new Point(75, 6);
            temp.lx.Name = "temp.lx" + temp.pan.Location.Y;// имена
            temp.ly.Name = "temp.ly" + temp.pan.Location.Y;
            temp.tbxx.Size = temp.tbxy.Size = new Size(60, 20);
            temp.tbxx.KeyPress += (this.key_press);// добавляем функцию обработки ввода
            temp.tbxy.KeyPress += (this.key_press);
            temp.tbxx.Location = new Point(15, 2);//координаты
            temp.tbxy.Location = new Point(89, 2);
            temp.tbxx.Name = "temp.tbxx" + temp.pan.Location.Y;//имена
            temp.tbxy.Name = "temp.tbxy" + temp.pan.Location.Y;
            temp.tbxx.TabIndex = 1;//очерёдность переключения с помощью Tab
            temp.tbxy.TabIndex = 2;
            Add_to_control(temp);// добавляем к родителям
            return temp;// возвращаем готовый элемент списка
        }
        private int is_not_empty(TextBox tbx)// проверка заполненности поля ввода координат (возвращает содержимое)
        {
            int res;// создаем результат типа int (можно вводить только целые значения)
            if (!Int32.TryParse(tbx.Text, out res))// проверяем введено ли значение
                res = Int32.MaxValue;// если нет, то присваиваем результату 2^32 (не самый лучший способ, но размеры экрана всё-таки намного меньше)
            return res;// возвращаем полученнное значение
         }
        private void key_press(object s, KeyPressEventArgs e)// проверка ввода
        {
            TextBox sender = (TextBox) s;// знаем, что событие создает TextBox, поэтому производим приведение типов
 
            if (e.KeyChar != 22)// если не производится вставка
                // Handled- это свойство KeyPressEventArgs, которое показывает, обработано ли нажатие клавиши
                // проверяем ввод Разрешено вводить "-" первым символом, цифру и нажимать Backspace
                if (!Char.IsDigit(e.KeyChar) && e.KeyChar != (char) Keys.Back &&
                    (e.KeyChar != '-' || (sender).SelectionStart != 0 ||
                     ((sender).Text.Contains("-") && !(sender).SelectedText.Contains("-"))))
                    e.Handled = true;
        }
        private void Add_field(object sender, EventArgs e)// если нажали кнопку "Добавить", появляется новая панель
        {
            pnls.Add(new_Panel(pnls[pnls.Count - 1]));
            pnls_num++;
        }
        private void Delete_field(object sender, EventArgs e)// по нажатию кнопки "Удалить" удаляется панель, если их количество больше 4
        {
            if (pnls_num > 4)
            {
                pnls[pnls.Count - 1].pan.Dispose();
                pnls.RemoveAt(pnls.Count - 1);
                pnls_num--;
            }
        }
        public void Calculate(object sender, EventArgs e)
        {
            //в функции производится считывание данных из TextBox'ов
            //проверка корректности и вызов функции рассчёта и отображения точек и сплайна
            bool correct_input = true; // флаг правильного ввода
            coords = new PointF[pnls_num + 2];// создаём массив точек, в которые помещаем данные из текстбоксов
            for (int i = 0; i < pnls_num; i++)// считываем данные из всех текстбоксов
            {
                if ((coords[i + 1].X = is_not_empty(pnls[i].tbxx)) == Int32.MaxValue ||// проверяем правильный ввод
                    (coords[i + 1].Y = is_not_empty(pnls[i].tbxy)) == Int32.MaxValue)
                {
                    correct_input = false;// если неправильный, то выходим из цикла
                    break;
                }
            }
            if (correct_input == false)// ошибка
                MessageBox.Show("Рассчёт не может быть произведён.\r\nНеверно (неполностью) заполнены поля ввода.");
            else
            {
                btmp = new Bitmap(pictureBox1.Width , pictureBox1.Height);// инициализируем битмап
                // для правильного отображения сплайна необходимо дважды добавить первую и последнюю точку
                coords[0] = coords[1];
                coords[pnls_num + 1] = coords[pnls_num];
                pictureBox1.Refresh();// обновляем pictureBox(стираем старое)
                graph = Graphics.FromImage(btmp);// инициализируем поверхность для рисования
                graph.TranslateTransform(pictureBox1.Width/2, pictureBox1.Height/2);// переносим начало координат в центр
                graph.ScaleTransform(1, -1);// меняем направление оси Y
                //рисуем координатные оси
                graph.DrawLine(axis_pen, 0, -pictureBox1.Height / 2, 0, pictureBox1.Height / 2);
                graph.DrawLine(axis_pen, -pictureBox1.Width / 2, 0,pictureBox1.Width / 2 , 0);
                Draw_spline();// рисуем сплайн
                Draw(null, null);// рисуем опорные точки
            }
        }
        public void Draw(object sender, PaintEventArgs e)
        {
            for (int i = 1; i < pnls_num+1; i++)
                graph.FillRectangle(points_brush, coords[i].X - 1, coords[i].Y - 1, 3, 3);// точки рисуются прямоугольниками
            pictureBox1.BackgroundImage = btmp;// переносим на битмап
        }
        public void Draw_spline()
        {
            for (int i = 1; i < pnls_num; i++)// в цикле по всем четвёркам точек
            {
                Coefficient(i);// считаем коэффициенты
                PointF[] points=new PointF[100];// создаём массив промежуточных точек
                for(int j=0;j<100;j++)
                {
                    float t = (float)((float)j/100);// шаг интерполяции
                    // передаём массиву точек значения по методу beta-spline
                    points[j].X = (a[0] + t * (a[1] + t * (a[2] + t * a[3])));
                    points[j].Y = (b[0] + t * (b[1] + t * (b[2] + t * b[3])));
                }
                graph.DrawCurve(spline_pen, points,0.1f);// рисуем кривую по полученным точкам
            }
        }
        public void Coefficient(int i)// в функции рассчитываются коэффициенты a0-a3, b0-b3
        {
            a[3] = (-coords[i - 1].X + 3*coords[i].X - 3*coords[i + 1].X + coords[i + 2].X)/6;
            a[2] = (coords[i - 1].X - 2*coords[i].X + coords[i + 1].X)/2;
            a[1] = (-coords[i - 1].X + coords[i + 1].X)/2;
            a[0] = (coords[i - 1].X + 4*coords[i].X + coords[i + 1].X)/6;
            b[3] = (-coords[i - 1].Y + 3*coords[i].Y - 3*coords[i + 1].Y + coords[i + 2].Y)/6;
            b[2] = (coords[i - 1].Y - 2*coords[i].Y + coords[i + 1].Y)/2;
            b[1] = (-coords[i - 1].Y + coords[i + 1].Y)/2;
            b[0] = (coords[i - 1].Y + 4*coords[i].Y + coords[i + 1].Y)/6;
        }
    }
}

Прикрепленный файлРазмер
Martyniuk-b_spline.rar74.08 кб
b_spline_program.rar10.21 кб