Фигуры на плоскости

• Отрезок

class Segment2d
{
public:
    Vector2d a, b;

    Segment2d () {}
    Segment2d ( const Vector2d & va, const Vector2d & vb ) : a(va), b(vb) {}

    Vector2d nearPoint ( const Vector2d & p ) const; // ближайшая точка отрезка к данной

    double qdis ( const Vector2d & p ) const // квадрат расстояния до точки p
    {
        return ::qmod ( p - nearPoint ( p ) );
    }
    double qmod () const { return ::qmod ( b - a ); } // квадрат длины отрезка

    template <typename T> Segment2d & operator *= ( const T & t )
    {
        a *= t, b *= t;
        return * this;
    }
};

inline bool operator != ( const Segment2d & s1, const Segment2d & s2 )
{
    return s1.a != s2.a || s1.b != s2.b;
}

inline bool operator == ( const Segment2d & s1, const Segment2d & s2 )
{
    return s1.a == s2.a && s1.b == s2.b;
}

inline double norm1 ( const Segment2d & s ) { return norm1 ( s.b - s.a ); } // единичная норма
inline double norm2 ( const Segment2d & s ) { return norm2 ( s.b - s.a ); } // квадратичная норма
inline double normU ( const Segment2d & s ) { return normU ( s.b - s.a ); } // бесконечная норма

• Прямая

class Line2d
{
public:
    Vector2d norm;
    double  dist;

    Line2d () {}
    Line2d ( const Vector2d & v, const double & d ) : norm ( v ), dist ( d ) {}
    Line2d ( const Vector2d & a, const Vector2d & b );

    double operator % ( const Vector2d & v ) const
    {
        return norm.x * v.x + norm.y * v.y + dist;
    }

    Line2d operator - () const
    {
        return Line2d ( - norm, - dist );
    }

    template<class T> Line2d & operator *= ( const T & t )
    {
        return *this = t ( *this );
    }

    Vector2d project ( const Vector2d & v ) const
    {
        return v - ( *this % v ) * norm;
    }

    Segment2d project ( const Segment2d & s ) const
    {
        return Segment2d ( project ( s.a ), project ( s.b ) );
    }

    Vector2d mirror ( const Vector2d & v ) const
    {
        return v - 2 * ( *this % v ) * norm;
    }

    Segment2d mirror ( const Segment2d & s ) const
    {
        return Segment2d ( mirror ( s.a ), mirror ( s.b ) );
    }
};

inline bool operator != ( const Line2d & a, const Line2d & b )
{
    return a.norm != b.norm || a.dist != b.dist;
}

inline bool operator == ( const Line2d & a, const Line2d & b )
{
    return a.norm == b.norm && a.dist == b.dist;
}

inline double operator % ( const Vector2d & a, const Line2d & b )
{
    return b.norm.x * a.x + b.norm.y * a.y + b.dist;
}
Класс Line2d предназначен для представления прямой линии на плоскости. Эта линия делит плоскость на две полуплоскости. Для одной из них расстояния до линии будут положительные, для другой - отрицательные. В классе есть два члена. Нормаль norm указывает в сторону положительной полуплоскости. Член dist равен расстоянию от линии до центра координат с учётом знака. В результате уравнение прямой имеет вид: norm.x * x + norm.y * y + dist = 0. Класс имеет три конструктора. Первый - пустой. Второй задаётся нормалью и расстоянием до центра координат. Третий - двумя точками через которые проходит прямая. Имеются операторы % и унарный минус. Оператор % вычисляет расстояние от точки до прямой. Унарный минус меняет местами положительную и отрицательную полуплоскости. Шаблон функций operator *= предназначен для преобразования прямых при помощи объектов разных типов. Функции-члены project возвращают проекцию точки или отрезка на прямую, а функции-члены mirror возвращают зеркальное отображённие точки или отрезка относительно прямой.

• Круг

class Circle2d
{
public:
    Vector2d o; // центр
    double   r; // радиус

    Circle2d () {}
    Circle2d ( const Vector2d & a, double b ) : o ( a ), r ( b ) {}

    Circle2d & operator *= ( const Conform2d & c )
    {
        o *= c; r *= c.magn; return *this;
    }
    // Площадь
    double getArea () const;
    // Периметр
    double getPerimeter () const;
};

• Эллипс

class Ellipse2d
{
public:
    Vector2d o;  // центр
    double a, b; // полуоси
    Spin2d spin; // поворот
    // Преобразование окружности в эллипс
    Affin2d getAffin2d() const;
    // Вычисление фокусов
    void getFoci ( Vector2d & f1, Vector2d & f2 ) const;
    // Площадь
    double getArea () const;
    // Периметр
    double getPerimeter () const;
};
Функция-член getAffin2d возвращает аффинное преобразование, которое отображает единичный круг в данный эллипс.

• Треугольник

class Triangle2d
{
public:
    Vector2d a, b, c;

    Triangle2d () {}
    Triangle2d ( const Vector2d & pa, const Vector2d & pb, const Vector2d & pc ) : a ( pa ), b ( pb ), c ( pc ) {}
    // Площадь
    double getArea () const;
    // Периметр
    double getPerimeter () const;
};

• Прямоугольник

class Rectangle2d
{
public:
    Vector2d o;  // центр
    double a, b; // полуоси
    Spin2d spin; // поворот
    // Площадь
    double getArea () const;
    // Периметр
    double getPerimeter () const;
};

• Ромб

class Rhombus2d
{
public:
    Vector2d o;  // центр
    double a, b; // полуоси
    Spin2d spin; // поворот
    // Площадь
    double getArea () const;
    // Периметр
    double getPerimeter () const;
};

• Параллелограмм

class Parallelogram2d
{
    Vector2d o, a, b; 
public:
    Parallelogram2d () {}
    Parallelogram2d ( const Vector2d & v1, const Vector2d & v2, const Vector2d & v3 ) :
        o ( v2 ), a ( v3 - v2 ), b ( v1 - v2 ) {}
    // Вершины
    void getVerts ( Vector2d vert[4] ) const;
    // Площадь
    double getArea () const;
    // Периметр
    double getPerimeter () const;
};
Параллелограмм задаётся любыми тремя последовательными вершинами.

Примеры использования всех этих классов можно посмотреть в приложении DEMO.

Описание классов Spin2d, Conform2d и Affin2d смотрите в разделе Преобразования на плоскости.
Описание класса Vector2d смотрите в разделе Вектора на плоскости.
Исходники находятся в файлах vector2d.h, vector2d.cpp.

Наверх