Литмир - Электронная Библиотека
A
A

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<n) {      // добавляет деления

        int dist = length/n;

        int x = xy.x+dist;

        for (int i = 0; i<n; ++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<n) { // добавляем деления

      int dist = length/n;

      int y = xy.y–dist;

      for (int i = 0; i<n; ++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);

}
 

203
{"b":"847443","o":1}