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

Класс Segment2d предназначен для представления отрезков на плоскости:

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 ); } // бесконечная норма

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

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;
}

Класс Circle2d предназначен для представления кругов на плоскости:

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

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

    Circle2d & operator *= ( const Conform2d & c )
    {
        o *= c; r *= c.magn; return *this;
    }
};

Класс Ellipse2d предназначен для представления эллипсов на плоскости. Функция-член getAffin2d возвращает аффинное преобразование, которое отображает единичный круг в данный эллипс:

class Ellipse2d
{
public:
    double a, b; // полуоси
    Spin2d spin; // поворот
    Vector2d o;  // центр

    Affin2d getAffin2d() const
    {
        LinTran2d t ( spin );
        t.x.x *= a; t.x.y *= b; 
        t.y.x *= a; t.y.y *= b; 
        return Affin2d ( t, o );
    }
    // Вычисление фокусов
    void getFoci ( Vector2d & f1, Vector2d & f2 ) const;
};

Класс Rectangle2d предназначен для представления прямоугольников на плоскости:

class Rectangle2d
{
public:
    double a, b; // полуоси
    Spin2d spin; // поворот
    Vector2d o;  // центр
};

Класс Rhomb2d предназначен для представления ромбов на плоскости:

class Rhomb2d
{
public:
    double a, b; // полуоси
    Spin2d spin; // поворот
    Vector2d o;  // центр
};
Следующие функции вычисляют площади фигур:
double area ( const Circle2d    & );
double area ( const Ellipse2d   & );
double area ( const Rectangle2d & );
double area ( const Rhomb2d     & );
А эти периметры:
double perimeter ( const Circle2d    & );
double perimeter ( const Ellipse2d   & );
double perimeter ( const Rectangle2d & );
double perimeter ( const Rhomb2d     & );

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

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

Наверх