Для представления данных мы используем класс Axis
Axis
состоит из линии, определенного количества делений оси и текстовой метки. Конструктор класса Axis
вычисляет координаты линии оси и (при необходимости) линий, используемых как деления оси.struct Axis:Shape {
enum Orientation { x, y, z };
Axis(Orientation d, Point xy, int length,
int number_of_notches=0, string label = "");
void draw_lines() const;
void move(int dx, int dy);
void set_color(Color c);
Text label;
Lines notches;
};
Объекты label
notches
остаются открытыми, поэтому пользователи могут ими манипулировать, например приписывать делениям цвет, отличающийся от цвета линии, или перемещать объект label
с помощью функции move()
в более удобное место. Объект класса Axis
— это пример объекта, состоящего из нескольких полунезависимых объектов.Конструктор класса Axis
number_ of_notches
больше нуля.Axis::Axis(Orientation d, Point xy, int length, int n, string lab)
:label(Point(0,0),lab)
{
if (length<0) error("bad axis length");
switch (d){
case Axis::x:
{
Shape::add(xy); // линия оси
Shape::add(Point(xy.x+length,xy.y));
if (0
int dist = length/n;
int x = xy.x+dist;
for (int i = 0; i
notches.add(Point(x,xy.y),Point(x,xy.y–5));
x += dist;
}
}
label.move(length/3,xy.y+20); // размещает метку под линией
break;
}
case Axis::y:
{ Shape::add(xy); // ось y перемещаем вверх
Shape::add(Point(xy.x,xy.y–length));
if (0
int dist = length/n;
int y = xy.y–dist;
for (int i = 0; i
notches.add(Point(xy.x,y),Point(xy.x+5,y));
y –= dist;
}
}
label.move(xy.x–10,xy.y–length–10); // размещает метку
// наверху
break;
}
case Axis::z:
error("ось z не реализована");
}
}
По сравнению с большинством реальных программ этот конструктор очень прост, но мы рекомендуем внимательно изучить его, поскольку он не настолько тривиален, как кажется, и иллюстрирует несколько полезных приемов. Обратите внимание на то, как мы храним линию в части класса Shape
Axis
(используя функцию Shape::add()
), хотя деления хранятся в виде отдельного объекта (notches
). Это позволяет нам манипулировать линией и делениями оси независимо друг от друга; например, мы можем раскрасить их в разные цвета. Аналогично метка была помещена в фиксированное положение, но, поскольку она является независимым объектом, мы всегда можем переместить ее в другое место. Для удобства используем перечисление Orientation
.Поскольку класс Axis
Axis
в целом. Рассмотрим пример.void Axis::draw_lines() const
{
Shape::draw_lines();
notches.draw(); // цвет делений может отличаться от цвета линии
label.draw(); // цвет метки может отличаться от цвета линии
}
Для рисования объектов notches
label
мы используем функцию draw()
а не draw_lines()
, чтобы иметь возможность использовать информацию о цвете, которая в них хранится. Объект класса Lines
хранится в разделе Axis::Shape
и использует информацию о цвете, хранящуюся там же.Мы можем задать цвет линии, деления и метки по отдельности, но с точки зрения красоты стиля этого лучше не делать, а задать их все с помощью одной функции.
void Axis::set_color(Color c)
{
Shape::set_color(c);
notches.set_color(c);
label.set_color(c);
}
Аналогично, функция Axis::move()
Axis
одновременно.void Axis::move(int dx, int dy)
{
Shape::move(dx,dy);
notches.move(dx,dy);
label.move(dx,dy);
}
15.5. Аппроксимация