Виталий Рычков
Фигуры вращения в программах на С++
Среди стандартного набора графических примитивов большинства программных бибилиотек так называемые фигуры вращения занимают в них лишь небольшую часть. Это в основном эллипсы, дуги, хорды и секторы.
В то же время крупные графические редакторы содержат более широкий набор фигур, построенных за счёт вращения вокруг центра окружности. В качестве примера можно привести автофигуры в приложениях Microsoft Office: это многогранники, звёзды, кольца и др.
Как создать подобные фигуры в собственном приложении?
В этой статье будут рассмотрены несколько простых примеров реализации фигур вращения и их отображение в окне программы на Visual C++.
Так выглядят эти фигуры в окне приложения...



Теперь рассмотрим, как реализованы эти фигуры в программном коде на С++.
Основой каждой фигуры является массив точек, координаты которых рассчитываются с применением функций  тригонометрии. При отображени фигуры в окне программы значения координат каждой точки пересчитываются с учётом габаритов данной фигуры и места её расположения.
Так выглядит базовый класс CXArray для всех представленных фигур...

class CXArray
{
  public
:
  const double
PI;
  enum
_ENUM
  {
    count = 120
  };
  CXArray(void
) : PI(acos(-1.0))
  {
    for (int
i = 0; i < count; ++i)
    {
      m_T[i] = 2.0*PI*i/count;
    }
  }
  virtual ~CXArray(void
)
  {
  }
  double m_T[count];
// Угол вращения
  double m_X[count];
// Координата X
  double m_Y[count];
// Координата Y
};

Классы, порождённые от CXArray, выполняют инициализацию массива координат m_X и m_Y в зависимости от  заданной формулы. Рассмотрим формулы зависимости величины радиуса вращения от угла поворота для каждой конкретной фигуры...

Фигура "Трилистник"
Rt = R0*cos(3T)


"Четырёхлепестковая" фигура
Rt = R0*cos(2T)


Фигура "Лимакона"
Rt = R0*(0.75+2cos(T))


Фигура "Звезда"
Rt = R0*(0.75-cos(5T)/5)


Фигура "Ромашка"
Rt = R0*(0.5+|cos(6T)/3|)


Фигура "Спираль Архимеда"
Rt = R0*T/π

Так выглядит реализация класса одной из приведённых в качестве примера фигур...

// Спираль Архимеда...
class CXSpiral : public CXArray
{
  public:
  CXSpiral()
  {
    for (int i = 0; i < count; ++i)
    {
      double dRad = m_T[i]/PI;
      m_X[i] = dRad*sin(m_T[i]);
      m_Y[i] = dRad*cos(m_T[i]);
    }
  }
  ~CXSpiral()
  {
  }
};

Чтобы отобразить какую-либо из этих фигур в окне программы (или на другом графическом устройстве), необходимо пересчитать массив координат из относительных единиц в реальные координаты графического устройства с учётом заданных размеров фигуры и её позиции относительно точки начала координат.
Затем все точки необходимо соединить отрезками, чтобы получилась одна сплошная линия.

Так выглядит в программном коде процедура отрисовки одной из представленных выше фигур...

// Отрисовка фигуры с помощью GDI+
void CMainFrame::DrawSpiral(Graphics& gr)
{
  CXSpiral x;
  PointF ptx[x.count];
  for ( int n = 0; n < x.count; n++)
  {
    ptx[n].X = (REAL)x.m_X[n]*50 + 600;
    ptx[n].Y = (REAL)x.m_Y[n]*50 + 330;
  }
  Pen pen(Color(128, 128, 255), 2);
  gr.DrawLines(&pen, ptx, x.count);
}

Полный код проекта демонстрационного приложения можно загрузить отсюда: RollShape.zip
Данный проект выполнен в Visual C++ 2005 с использованием библиотеки Windows Template Library (WTL) 8.0
Благодарю за внимание