Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

win.attach(s2);

win.attach(s3);

win.wait_for_button;

Сначала определяем несколько констант, чтобы не перегружать нашу программу “магическими константами”. Затем создаем окно, определяем функции, связываем их с окном и передаем контроль графической системе, которая выполняет реальное рисование на экране.

Все это делается по шаблону, за исключением определений трех объектов класса

Function
:
s
,
s2
и
s3
.

Function s(one,r_min,r_max,orig,n_points,x_scale,y_scale);

Function s2(slope,r_min,r_max,orig,n_points,x_scale,y_scale);

Function s3(square,r_min,r_max,orig,n_points,x_scale,y_scale);

Каждый объект класса

Function
определяет, как их первый аргумент (функция с одним аргументом типа
double
, возвращающая значение типа
double
) будет нарисован в окне. Второй и третий аргументы задают диапазон изменения переменной
x
(аргумента изображаемой функции). Четвертый аргумент (в данном случае
orig
) сообщает объекту класса
Function
, в каком месте окна расположено начало координат
(0,0)
.

Если вы считаете, что в таком количестве аргументов легко запутаться, то мы не станем спорить. В идеале аргументов должно быть как можно меньше, поскольку большое количество аргументов сбивает с толку и открывает возможности для ошибок. Однако пока мы не можем обойтись без них. Смысл последних трех аргументов мы объясним в разделе 15.3, а пока заметим, что первый из них задает метку графика.

Мы всегда стараемся сделать так, чтобы графики были понятны без дополнительных разъяснений. Люди не всегда читают текст, окружающий рисунок, поэтому он часто оказывается бесполезным. Все, что мы изображаем на рисунках, должно помочь читателям понять его. В данном случае мы просто ставим на каждом графике метку. Код для создания метки задается тремя объектами класса
Text
(см. раздел 13.11).

Text ts(Point(100,y_orig–40),"one");

Text ts2(Point(100,y_orig+y_orig/2–20),"x/2");

Text ts3(Point(x_orig–100,20),"x*x");

win.set_label("Function graphing: label functions");

win.wait_for_button;

С этого момента на протяжении всей главы мы будем пропускать повторяющийся код, связывающий фигуру с окном, присваивающий ей метку и ожидающий щелчка на кнопке Next.

Тем не менее этот рисунок еще нельзя считать законченным. Мы уже отметили, что наклонная линия
x/2
касается параболы
x*x
в точке
(0,0)
, а график функции one пересекает линию
x/2
в точке
(2,1)
, но это известно лишь нам; для того чтобы это стало очевидно читателям, на рисунке следует нанести оси координат.

Код для построения осей состоит из объявлений двух объектов класса

Axis
(раздел 15.4).

const int xlength = xmax–40; // оси должны быть чуть меньше окна

const int ylength = ymax–40;

Axis x(Axis::x,Point(20,y_orig), xlength,

xlength/x_scale, "one notch == 1");

Axis y(Axis::y,Point(x_orig, ylength+20),

ylength, ylength/y_scale, " one notch == 1");

Использование значения

xlength/x_scale
в качестве параметра, задающего количество делений, позволяет использовать целочисленные отметки 1, 2, 3 и т.д. Выбор точки
(0,0)
в качестве начала координат является общепринятым. Если хотите, чтобы начало координат было не в центре, а, как обычно, в левом нижнем углу окна (раздел 15.6), вы легко сможете сделать это. Кроме того, для того чтобы различать оси, можно использовать цвет.

x.set_color(Color::red);

y.set_color(Color::red);

Итак, получаем результат, показанный ниже.

Такой рисунок вполне приемлем, но по эстетическим причинам стоило бы сдвинуть линии немного вниз. Кроме того, было бы неплохо отодвинуть метки оси x немного влево. Однако мы не будем этого делать, поскольку эстетический вид графика можно обсуждать до бесконечности. Одно из профессиональных качеств программиста заключается в том, чтобы знать, когда остановиться и потратить сэкономленное время на что-нибудь более полезное (например, на изучение новых методов или на сон). Помните: “лучшее — враг хорошего”.

15.3. Класс Function

Определение класса графического интерфейса

Function
приведено ниже.

struct Function:Shape {

// параметры функции не хранятся

Function(Fct f,double r1,double r2,Point orig,

int count = 100,double xscale = 25,double yscale = 25);

};

Класс

Function
является производным от класса
Shape
. Конструктор класса
Function
генерирует множество отрезков линий и хранит их в членах класса
Shape
. Эти отрезки линий аппроксимируют значения функции
f
. Значения функции
f
вычисляются count раз в точках, равномерно распределенных по интервалу
[r1:r2]
.

  • Читать дальше
  • 1
  • ...
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: