|
• Отрезок
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 смотрите в разделе Преобразования на плоскости.
|