Головна » C++ Builder: построение графиков. Часть 1. Косинусы (cos)

C++ Builder: построение графиков. Часть 1. Косинусы (cos)

Начинаю серию заметок о построении графиков средствами C++ Builder. Сначала, пожалуй, напишу о «прорисовке» графика на компоненте Image. А потом, если кому-то будет интересно, поговорим о компоненте Chart (жутко полезная штука, я вам скажу).

В серию о построении графиков в C++ Builder уже вошли такие посты:

  1. Построение косинусов (cos);
  2. Построение синусов (sin);
  3. Построение тангенсов (tg);
  4. Построение котангенсов (ctg).

В общем, этот пост посвящен построению графика косинуса (cos). Функция при этом имеет вид cos(X) или cos(X)+k, или даже такой a*cos(X)+k.

Первым делом нам понадобится установить компонент Image на форму. Далее можно переходить непосредственно к «прорисовке». Для начала нам понадобится нарисовать градацию. Это можно сделать так:

// выделяем область, на которой будем рисовать 
// (при этом оставив небольшие поля по краям)
LX=Image1->Width-50;
LY=Image1->Height-30;

//примем ориентировочные значения максимума и минимума 
// (понадобятся для выделения максимума и минимума функции)
  Ymax=-100;
  Ymin=100;

//устанавливаем голубой цвет кисти и рисуем прямоугольник
Image1->Canvas->Pen->Color=clBlue;
Image1->Canvas->Rectangle(50,40,LX,LY);

//устанавливаем серый цвет кисти (прерывистая линия)
Image1->Canvas->Pen->Color=clGray;
Image1->Canvas->Pen->Style=psDash;

//циклически прорисовываем девять линий градации
for (i=1;i<=9;i++) { A[i]=50+LX/11*i; Image1->Canvas->MoveTo(A[i],40);
 Image1->Canvas->LineTo(A[i],LY);
}

//циклически выводим значения возле прорисованной линии
 float C[11];
 for (i=0;i<=10;i++) { C[i]=50+LX/11*i; AnsiString S1 = FloatToStrF(Xmin+((Xmax-Xmin)/10)*i,ffFixed,5,2); Image1->Canvas->TextOutA(C[i]-10,LY+5,S1);
}

//циклически прорисовываем девять линий градации
for (i=1;i<=9;i++) { A[i]=50+LY/11*i; Image1->Canvas->MoveTo(50,A[i]-10);
 Image1->Canvas->LineTo(LX,A[i]-10);
}

//устанавливаем красный цвет кисти (сплошная линия)
Image1->Canvas->Pen->Style=psSolid;
Image1->Canvas->Pen->Color=clRed;

//определяем масштаб по оси X 
if ((Xmax-Xmin)==0) MasX=LX-50;
else MasX=(LX-50)/(Xmax-Xmin);

//делаем рисунок видимым
Image1->Visible=true;

Учтите, что Xmax (максимальное значение по X) и Xmin (минимальное значение по X) необходимо задать заранее. Также следует задать величину шага – dX. Кроме того, можно задать константу k (в случае, если функция имеет вид cos(X)+k) и a (в случае, если функция имеет вид a*cos(X)+k).

После этого можно перейти непосредственно к построению графика функции. Я делала это так:

//циклически рассчитываем значения функции и определяем 
// ее максимум и минимум)
for (X=Xmin;X<=Xmax;X+=dX)
  {
   Y=a*cos(X)+k;
   if(Ymax<Y) Ymax=Y; if(Ymin>Y) Ymin=Y;
  }

//определяем масштаб по оси Y
 MasY=(LY-40)/(Ymax-Ymin);

//циклически выводим числовые значения возле прорисованных 
// градационных линий
 float B[11];
 for (i=0;i<=10;i++) { B[i]=35+LY/11*i; AnsiString S = FloatToStrF(Ymax-((Ymax-Ymin)/10)*i,ffFixed,5,2); Image1->Canvas->TextOutA(20,B[i],S);
}

// и вот теперь переходим непосредственно к рисованию
Image1->Canvas->MoveTo(50,LY-(Ymin*(-1)+a*cos(Xmin))*MasY);

 for (X=Xmin;X<=Xmax;X+=dX) { Y=a*cos(X); PY=LY-(Ymin*(-1)+Y)*MasY; PX=X*MasX+50; Image1->Canvas->LineTo(PX-Xmin*MasX,PY);
  }

Результат работы программы представлен ниже (установленные параметры: Xmax=10, Xmin=0, dX=0.2, a=1, k=0).

Построенный график функции a*cos(X)+k

Вроде ничего не забыла. Будут вопросы – прошу в комментарии.

femil

43 коментарі до “C++ Builder: построение графиков. Часть 1. Косинусы (cos)

  1. Хотелось бы узнать возможно ли построение графика функции при помощи компонента Chart так что бы промежуток “х” и шаг “х” (дельта) указывал сам пользователь программы (к примеру при помощи Edit).

    1. Естественно, можно. Так даже проще получится (не придется считать масштаб +
      часть настроек можно произвести в компоненте “руками” заранее).
      Само рисование делается так:

      Series1->AddXY(X,Y,"",clRed);

      где Series1 – созданная в Chat’е “серия” (задан вариант графика)
      Х и Y – берем циклически (с учетом заданного шага).
      clRed – цвет линии.
      между “” можно вставить название функции.
      Вот и вся премудрость.
      Кстати, спасибо за идею – в ближайшем будущем напишу об этом постик =)

      1. Спасибо за ответ=)
        уже сделал с Chart’ом намного проще получается
        вот еще вопрос:
        возможно ли задать функцию переменной?
        я пытался сделать через преобразование StrToFloat, но у меня выводит ошибку.

        float q;
        q=StrToFloat(Edit1->Text);
        for(float x = k; x<j; x+=l)//k<xAddXY(x,y);
        }

        в Edit1 вводим функцию.

        Подскажите если есть какие то мысли по данному поводу =)
        Буду благодарен

        1. Нет, так не выйдет.
          если q – функция, то преобразовать ее из строки в вещественный тип данных не представляется возможным. Это раз. Два – подключать вообще не известную функцию “по горячему” тоже не получится. Тут варианта два: либо разбиение строки и сравнение ее с заранее заданной маской (разбивать можно с помощью функции SubString). После можно частично преобразовать полученный результат.
          Либо замена Эдита (компонента, в смысле) на Комбобокс с набором заранее введенных функций.
          Как-то так.

          1. Спасибо, буду комбобоксом пробовать 🙂

  2. Плохое описание, если в коде пытаешься что то изменить, то появляются сплошные ошибки. Не расписано, что и как нужно поменять, чтобы стало так то, так то. Приходится самому всё додумывать. зачем то представлен готовый код(не как обычно выкладывают на сайтах) ,но элементарно нет ввода переменных, т е нельзя просто взять копирнуть код и посмотреть что там такое. Нельзя побаловаться в таком коде. Ничего не упоминается о подключенных библиотеках – настоящие чайники не разберутся.

    Например : //циклически прорисовываем девять линий градации
    for (i=1;iCanvas->MoveTo(50,A[i]-10);
    Image1->Canvas->LineTo(LX,A[i]-10);
    }

    непонятно почему именно 9 линий, непонятно почему компилятор ругается на “A[i]” , так же не ясно почему я не могу изменить колличество этих линий и т д.

    ВСЁ нужно подкреплять хоть какими то словами ,а не Я РИСУЮ 9 линий…
    должна быть оговорка вы можете изменить 9 на 109 ,НО при этом нужно поменять там то ,там то, так как оно связано и т п. Понимаете?

    1. Понимаю. Но переписывать не буду. Если у вас есть какие-то конкретные вопросы по коду – я постараюсь ответить. Если получена какая-то ошибка, то лучше сразу приводите и ее текст, и код. Как-то так )

      1. Быстро отвечаете)
        Девушка, а нельзя вас немного о другом спросить?но тоже о построении графика в билдере не имеичке)
        нужна помощь )

        1. Сравнительно. Спрашивайте.
          Кстати, если речь о построение при помощи компонента чарт, то есть соответствующий постик…

          1. Хотелось бы поподробней о том, как связать свой график именно с размером имейджа.
            Не получается, у меня например параболическая функция и естественно она при определённых значениях выходит далеко за пределы.
            не могу понять и связать ваше построение со своим.
            И можно ли чтобы числа которые высчитываются для градаций, каждый раз менялись.
            Т е как бы подстраивались под мой график.
            Я вам вчера писал в “Написать мне” там подробнее описана моя проблема)

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

            По поводу ресайза: масштабировать рисунок надо, а не сам имейдж.
            В первом куске кода мы определяем масштаб по Х (строки 49-50), во втором (до 11 строки) определяем масштаб по игреку. Уже после этот масштаб используется для вмещения рисунка в отведенное поле.

            И можно ли чтобы числа которые высчитываются для градаций, каждый раз менялись.
            Т е как бы подстраивались под мой график.

            Приведенный код полностью этим требованиям соответствует. Почему вы не можете просто скопировать?

          3. Потому что просто скопировать не удаётся, компилятор ругаться начинает)
            И проблема в том что я не понимаю ваш код и по этой причине не могу подстроить его под себя. У меня например
            y=-((x*x*mp)/(e*134*2)); такая всё кроме иксов является константами которые берутся либо из эдитов,либо из трек бара.
            что мне за Хмин Хмакс обозначать я не понимаю.

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

            если на моём примере сможете показать , то я пойму, т к ваш не понятен вообще(
            _____________________________
            int a=Image1->Width;
            int b=Image1->Height;
            int O=TrackBar1->Position;
            int y,x;
            int mp=TrackBar2->Position;
            int e=StrToInt ((Edit1->Text));

            for (x=0;xCanvas->Pen->Color = clRed;
            Image1->Canvas->Pen->Width=1;

            Image1->Canvas->MoveTo((a-a*0.9), (0.9*b));
            x++;

            y=-((x*x*mp)/(e*134*2));

            Image1->Canvas->LineTo((a-a*0.9+x),(0.9*b+y));

            }

          4. Вот этот кусок кода, это что:

            for (x=0;xCanvas->Pen->Color = clRed;

            ?
            Если у вас идет построение от 0 до какого-то конкретного числа, то это и есть ваши мин. и макс. по х.

            В вашем примере нет масштабирования – нужно найти максимум и минимум функции, посчитать масштаб, а потом ее строить.

          5. Смотрите, это код именно для прорисовки градаций.
            который я пытался под свой максимум приспособить и миллион ошибок выдаёт этот код, хотя я лишь поставил чтобы Хмакс вводимый был и игрик макс
            ____

            {
            int LX, LY, i, MasY, MasX;
            int Ymin=0;

            LX=Image1->Width*0.9;
            LY=Image1->Height*0.9;

            int mp=TrackBar2->Position;
            int e=StrToInt ((Edit1->Text));

            int O=TrackBar1->Position;
            int KK=((O*O*mp)/(e*134*2));

            Image1->Canvas->Pen->Color=clGray;
            Image1->Canvas->Pen->Style=psDash;

            int A[10];

            for (i=1;iCanvas->MoveTo(A[i],40);
            Image1->Canvas->LineTo(A[i],LY);
            }

            float C[11];
            for (i=0;iCanvas->TextOutA(C[i]-4,LY+10,S1);
            }

            for (i=1;iCanvas->MoveTo(50,A[i]-10);
            Image1->Canvas->LineTo(LX-20,A[i]-10);
            }

            Image1->Canvas->Pen->Style=psSolid;

            //îïðåäåëÿåì ìàñøòàá ïî îñè X
            if ((O)==0) MasX=LX-50;
            else MasX=(LX-50)/(O);

            float B[11];
            for (i=0;iCanvas->TextOutA(20,B[i],S);
            }

            Image1->Visible=true;
            }

          6. Тааак)с градацией исправил , получилось.
            сейчас если график не добью, то обращусь)
            я вам уже надоел наверно?

  3. Можно с вами на 10 минут онлайн пообщаться как нибудь?если можно то на этих выходных бы, у меня московское время)

  4. вот эта штука должна переделана с вашей вроде всё верно, но график какой-то странный, не такой вообщем)и зачем вообще в этом коде переделываются значения по оси ординат?
    они становятся не верные и график все -равно не под размер(((
    ___

    void __fastcall TForm1::Button8Click(TObject *Sender)
    {
    int LX, LY, i, MasY, MasX;
    int Ymin=0;
    int Xmin=0;

    LX=Image1->Width*0.9;
    LY=Image1->Height*0.9;
    int mp=TrackBar2->Position;
    int e=StrToInt ((Edit1->Text));

    int O=TrackBar1->Position;
    int Xmax=TrackBar1->Position;
    int Ymax=((O*O*mp)/(e*134*2));

    int X, PX,PY;
    int Y;

    for (X=Xmin;X<=Xmax;X++)
    {
    Y=X*X*mp/e/134/2;
    if(YmaxY) Ymin=Y;
    }

    MasY=(LY-40)/(Ymax-Ymin);

    float B[11];
    for (i=0;iCanvas->TextOutA(20,B[i],S);
    }

    Image1->Canvas->MoveTo(LX-0.9*LX,LY*0.9);

    for (X=Xmin;XCanvas->LineTo(PX-Xmin*MasX,PY);

    } }

    1. Добрый вечер. Смотрю только последний код (это, я так понимаю, последний вариант).
      Первый вопрос: что это за способ определения Ymax – нужно перебрать все значения Y, а не забить первое попавшееся в максимум. Это раз. Два, что это за строка:

      if(YmaxY) Ymin=Y;

      Вы на пхп, чтоль пишете? – Билдеру такое не глотнуть (в том понимании, в котором его глотает пхп.

      float B[11];
      for (i=0;iCanvas->TextOutA(20,B[i],S);
      }

      Это тоже какие-то непонятнки.
      И вот тут

       for (X=Xmin;XCanvas->LineTo(PX-Xmin*MasX,PY);
      
      } }

      P.S.: “В форме комментирования есть тег “Код” – пользуйте, тогда проблем будет в разы меньше”

      По поводу поговорить онлайн – только поздней ночью (как сейчас) – раньше я постоянно занята. Если я онлайн – я обязательно читаю почту и отвечаю на комментарии )))

    2. Опять же: масштабирование! Ни по оси х, ни по оси у я его не вижу.
      Либо не весь код, либо вы просто умножаете на 0.

      Комментарии вам приходят (если вы на них подписаны) с моей почты: пришлите туда программу – так будет быстрее и эффективнее.

      1. Доброе утро)
        Нет , пишу то на с++) у меня в разных кнопочках пока маштабирование и график, чтобы по очереди всё наладить.

        “if(YmaxY) Ymin=Y;” это из вашего кода, при копировании знак > либи < какой там был пропал)

        Маштабирование получилось, поэтому его не кидаю. Кину вам весь весь код сейчас,- глянете)

          1. Код я посмотрела. Логических ошибок в нем не вижу. Результата тоже не вижу, т.к. у меня нет времени собирать конструктор (ведь просто скопировать это нельзя) – событие для каждого компонента должно быть создано средствами билдера, а не простым копированием.

            У вас вот здесь, кстати, правильный результат расчета

            Y=X*X*mp/e/134/2;

            ?

            ЗЫ: чтоб ВП не удалял куски кода – следует использовать тег “Код” (кнопка над формой для комментариев).

          2. да, верный)ладно, спасибо вам большое, буду дальше сам разбираться)

  5. Подскажи пожалуйста как сделать что график можно было сделать
    объекте Chart ( можешь под Chart на писать код программы )??
    Заранее Спасибо!!

  6. Составил проект в виде текстового редактора. Все стандартные процедуры для текстового редактора сделал т.е. кнопки главного меню:Открыть, сохранить и т.д. Создал свою кнопку “ВЫЧИСЛИТЬ” в главном меню текстового редактора. Ввел Форму2.Проблема в том, что хочу с помощью нажатия кнопки “ВЫЧИСЛИТЬ” вызвать Форму2. Процедуру вызова одной формы из другой, с помощью Form2ShowModal(); мне понятна. Пробовал пойти по данному пути выдает ошибку. Если не трудно подскажите WAY. Заранее благодарю.

    1. В шапку проекта нужно добавить заглавный файл второй формы, например так:

      #include "Unit2.h"
      

      А непосредственно вызов можно также сделать таковым:

       Form2->Visible=true;
      
  7. Сделал. Не получается. Почему-то Unit2.h выделяет красным цветом:class TForm1 : public TForm. Если не трудно подскажите. Please PEAPLE.
    Вот мой код.
    #include
    #pragma hdrstop

    #include “Unit123.h”
    #include “Unit2.h”
    //—————————————————————————
    #pragma package(smart_init)
    #pragma resource “*.dfm”
    TForm1 *Form1;

    void __fastcall TForm1::N2Click(TObject *Sender) (это кнопка из главного меню текстового редактора)
    {
    Form2->Visible=true;
    }

  8. А как просто по набору точек построить график? можете примерно набросать?

    1. Набор точек у вас в массиве? Если да – просто циклически перебирайте элементы. Если нет – сначала нужно засунуть в массив, а потом перебирать. Не пойму, в чем конкретно возникает проблема?

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Повернутись до верху