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

Вход на сайт

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

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

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

dobryj den, popytalas otkryt prikreplionnyj fail ctoby posmotret kak rabotaet, no mne ego ne pokazyvaet vydajet osibku. Pochemu?
Очень интересно! ии сайт крутой жалко что умирает(
У Вас число превысит максимальное число int. Можно использовать в Вашем случае uint, но лучше все переписать на double.
Добавление к программе строки glutReshapeFunc(changeSize); приводит к тому, что треугольник перестаёт совсем отрисовываться.
Выдаёт ошибку glut32.dll не найден! При том, что он лежит в System32! Всё решил) Нужно отправить не в System32, а в System.

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

Рейтинг@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 кб