Начинаю серию заметок о построении графиков средствами C++ Builder. Сначала, пожалуй, напишу о «прорисовке» графика на компоненте Image
. А потом, если кому-то будет интересно, поговорим о компоненте Chart
(жутко полезная штука, я вам скажу).
В серию о построении графиков в C++ Builder уже вошли такие посты:
- Построение косинусов (cos);
- Построение синусов (sin);
- Построение тангенсов (tg);
- Построение котангенсов (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).
Вроде ничего не забыла. Будут вопросы – прошу в комментарии.
Хотелось бы узнать возможно ли построение графика функции при помощи компонента Chart так что бы промежуток “х” и шаг “х” (дельта) указывал сам пользователь программы (к примеру при помощи Edit).
Естественно, можно. Так даже проще получится (не придется считать масштаб +
часть настроек можно произвести в компоненте “руками” заранее).
Само рисование делается так:
где Series1 – созданная в Chat’е “серия” (задан вариант графика)
Х и Y – берем циклически (с учетом заданного шага).
clRed – цвет линии.
между “” можно вставить название функции.
Вот и вся премудрость.
Кстати, спасибо за идею – в ближайшем будущем напишу об этом постик =)
Спасибо за ответ=)
уже сделал с Chart’ом намного проще получается
вот еще вопрос:
возможно ли задать функцию переменной?
я пытался сделать через преобразование StrToFloat, но у меня выводит ошибку.
в Edit1 вводим функцию.
Подскажите если есть какие то мысли по данному поводу =)
Буду благодарен
Нет, так не выйдет.
если q – функция, то преобразовать ее из строки в вещественный тип данных не представляется возможным. Это раз. Два – подключать вообще не известную функцию “по горячему” тоже не получится. Тут варианта два: либо разбиение строки и сравнение ее с заранее заданной маской (разбивать можно с помощью функции SubString). После можно частично преобразовать полученный результат.
Либо замена Эдита (компонента, в смысле) на Комбобокс с набором заранее введенных функций.
Как-то так.
Спасибо, буду комбобоксом пробовать 🙂
Всегда пожалуйста =)
Спасибо от чайника
Всегда пожалуйста )
Заходите еще =)
ждем обещанную заметку о chart 🙂
А есть уже такая заметка – вот =)
Плохое описание, если в коде пытаешься что то изменить, то появляются сплошные ошибки. Не расписано, что и как нужно поменять, чтобы стало так то, так то. Приходится самому всё додумывать. зачем то представлен готовый код(не как обычно выкладывают на сайтах) ,но элементарно нет ввода переменных, т е нельзя просто взять копирнуть код и посмотреть что там такое. Нельзя побаловаться в таком коде. Ничего не упоминается о подключенных библиотеках – настоящие чайники не разберутся.
Например : //циклически прорисовываем девять линий градации
for (i=1;iCanvas->MoveTo(50,A[i]-10);
Image1->Canvas->LineTo(LX,A[i]-10);
}
непонятно почему именно 9 линий, непонятно почему компилятор ругается на “A[i]” , так же не ясно почему я не могу изменить колличество этих линий и т д.
ВСЁ нужно подкреплять хоть какими то словами ,а не Я РИСУЮ 9 линий…
должна быть оговорка вы можете изменить 9 на 109 ,НО при этом нужно поменять там то ,там то, так как оно связано и т п. Понимаете?
Понимаю. Но переписывать не буду. Если у вас есть какие-то конкретные вопросы по коду – я постараюсь ответить. Если получена какая-то ошибка, то лучше сразу приводите и ее текст, и код. Как-то так )
Быстро отвечаете)
Девушка, а нельзя вас немного о другом спросить?но тоже о построении графика в билдере не имеичке)
нужна помощь )
Сравнительно. Спрашивайте.
Кстати, если речь о построение при помощи компонента чарт, то есть соответствующий постик…
Хотелось бы поподробней о том, как связать свой график именно с размером имейджа.
Не получается, у меня например параболическая функция и естественно она при определённых значениях выходит далеко за пределы.
не могу понять и связать ваше построение со своим.
И можно ли чтобы числа которые высчитываются для градаций, каждый раз менялись.
Т е как бы подстраивались под мой график.
Я вам вчера писал в “Написать мне” там подробнее описана моя проблема)
Надеюсь, вы скопировали, то, что писали через обратную связь, т.к. я ничего не получила (скорее всего хостинг ступил и не отправил).
По поводу ресайза: масштабировать рисунок надо, а не сам имейдж.
В первом куске кода мы определяем масштаб по Х (строки 49-50), во втором (до 11 строки) определяем масштаб по игреку. Уже после этот масштаб используется для вмещения рисунка в отведенное поле.
Приведенный код полностью этим требованиям соответствует. Почему вы не можете просто скопировать?
Потому что просто скопировать не удаётся, компилятор ругаться начинает)
И проблема в том что я не понимаю ваш код и по этой причине не могу подстроить его под себя. У меня например
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));
}
Вот этот кусок кода, это что:
?
Если у вас идет построение от 0 до какого-то конкретного числа, то это и есть ваши мин. и макс. по х.
В вашем примере нет масштабирования – нужно найти максимум и минимум функции, посчитать масштаб, а потом ее строить.
Смотрите, это код именно для прорисовки градаций.
который я пытался под свой максимум приспособить и миллион ошибок выдаёт этот код, хотя я лишь поставил чтобы Хмакс вводимый был и игрик макс
____
{
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;
}
Тааак)с градацией исправил , получилось.
сейчас если график не добью, то обращусь)
я вам уже надоел наверно?
Можно с вами на 10 минут онлайн пообщаться как нибудь?если можно то на этих выходных бы, у меня московское время)
вот эта штука должна переделана с вашей вроде всё верно, но график какой-то странный, не такой вообщем)и зачем вообще в этом коде переделываются значения по оси ординат?
они становятся не верные и график все -равно не под размер(((
___
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);
} }
Добрый вечер. Смотрю только последний код (это, я так понимаю, последний вариант).
Первый вопрос: что это за способ определения Ymax – нужно перебрать все значения Y, а не забить первое попавшееся в максимум. Это раз. Два, что это за строка:
Вы на пхп, чтоль пишете? – Билдеру такое не глотнуть (в том понимании, в котором его глотает пхп.
Это тоже какие-то непонятнки.
И вот тут
P.S.: “В форме комментирования есть тег “Код” – пользуйте, тогда проблем будет в разы меньше”
По поводу поговорить онлайн – только поздней ночью (как сейчас) – раньше я постоянно занята. Если я онлайн – я обязательно читаю почту и отвечаю на комментарии )))
Опять же: масштабирование! Ни по оси х, ни по оси у я его не вижу.
Либо не весь код, либо вы просто умножаете на 0.
Комментарии вам приходят (если вы на них подписаны) с моей почты: пришлите туда программу – так будет быстрее и эффективнее.
Доброе утро)
Нет , пишу то на с++) у меня в разных кнопочках пока маштабирование и график, чтобы по очереди всё наладить.
“if(YmaxY) Ymin=Y;” это из вашего кода, при копировании знак > либи < какой там был пропал)
Маштабирование получилось, поэтому его не кидаю. Кину вам весь весь код сейчас,- глянете)
http://
yadi.sk/d/d-If7tVn4C5UwКод я посмотрела. Логических ошибок в нем не вижу. Результата тоже не вижу, т.к. у меня нет времени собирать конструктор (ведь просто скопировать это нельзя) – событие для каждого компонента должно быть создано средствами билдера, а не простым копированием.
У вас вот здесь, кстати, правильный результат расчета
?
ЗЫ: чтоб ВП не удалял куски кода – следует использовать тег “Код” (кнопка над формой для комментариев).
да, верный)ладно, спасибо вам большое, буду дальше сам разбираться)
Удачи вам )
Подскажи пожалуйста как сделать что график можно было сделать
объекте Chart ( можешь под Chart на писать код программы )??
Заранее Спасибо!!
А вот здесь ответа на вопрос не нашлось?)
Извини просто не заметил ))
бывает )))
Составил проект в виде текстового редактора. Все стандартные процедуры для текстового редактора сделал т.е. кнопки главного меню:Открыть, сохранить и т.д. Создал свою кнопку “ВЫЧИСЛИТЬ” в главном меню текстового редактора. Ввел Форму2.Проблема в том, что хочу с помощью нажатия кнопки “ВЫЧИСЛИТЬ” вызвать Форму2. Процедуру вызова одной формы из другой, с помощью Form2ShowModal(); мне понятна. Пробовал пойти по данному пути выдает ошибку. Если не трудно подскажите WAY. Заранее благодарю.
В шапку проекта нужно добавить заглавный файл второй формы, например так:
А непосредственно вызов можно также сделать таковым:
Сделал. Не получается. Почему-то 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;
}
Первая строка у вас
Может, ее следует удалить?)))
А почему билдер ругается на «A[i]»?????
Объявите переменную:
А как просто по набору точек построить график? можете примерно набросать?
Набор точек у вас в массиве? Если да – просто циклически перебирайте элементы. Если нет – сначала нужно засунуть в массив, а потом перебирать. Не пойму, в чем конкретно возникает проблема?