Все значения в Python являются объектами определённых классов. Чтобы узнать экземпляром какого класса является значение, используем функцию type().
Любой объект хранит в себе набор членов класса. К ним относятся поля - состояние объекта и методы - функции, которые меняют состояние объект.
Опишем класс Point для представление точки на плоскости.
Описание простейшего класса:
Для обращения к полям и методам класса используется оператор . (точка):
Объявим функцию init(), которая в качестве аргументов будет принимать объект типа Point и значения полей x и y.
Инициализация объекта может быть размещена в теле класса. Для этого используется метод с именем __init__().
Первый параметр метода __init()__ будет ссылкой на инициализируемый объект.
Этот параметр может иметь произвольное имя, но принято называть его self.
Опишем ещё одну функцию dist(p1, p2) с помощью которой рассчитаем расстояние между точками p1 и p2.
Функцию dist(p1, p2) так же можно оформить как метод класса Point.
Первый параметр любого метода класса - это ссылка на объект, который вызвал метод.
Специальные методы добавляют классу поведение, аналогичное встроенным в Python классам.
__str__(self) - вызывается при преобразовании объекта в строковый тип.__add__(self, other) - вызывается при использовании оператора +.__eq__(self, other) - вызывается при использовании оператора ==.Преобразование точки в строку:
Реализация оператора == для двух точек:
Векторное произведение \(\vec{a} \times \vec{b}\) двух векторов \(\vec{a}=(x_1, y_1)\) и \(\vec{b}=(x_2, y_2)\) применятся в ряде алгоритмов.
Зачастую для решения задач будет достаточно вычислить значение координаты \(z\) результирующего вектора.
В случае векторного умножения векторов лежащих в плоскости \(XY\), значение координаты \(z\) вычисляется следующим образом1: \[ x_1y_2-x_2y_1 \]
С помощью векторного произведения можем определить направление поворота вектора \(\vec{b}\) относительно вектора \(\vec{a}\):
Vector2Создадим класс Vector2 на основе класса Point с помощью наследования.
Разместим в классе метод для вычисления векторного произведения:
Родительский класс указывается в круглых скобках после имени класса.
Добавим в класс Vector2 методы для сложения и вычитания векторов.
Методы __add__() и __sub__() возвращают новый экземпляр класса Vector2.
Положение точки относительно прямой
Даны точки \(s_1\) и \(s_2\). Определить с какой стороны от вектора \(\vec{s_1 s_2}\) находится точка \(p\).
Положение определим, вычислив векторное произведение \((p - s_1) \times (p - s_2)\). Если оно положительно, то \(p\) слева от прямой, если отрицательно - справа, равно нулю - все точки лежат на одной прямой.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"x:{self.x}, y:{self.y}"
class Vector2(Point):
def cross_prod(self, v2):
return self.x * v2.y - self.y * v2.x
def __add__(self, v2):
return Vector2(self.x + v2.x, self.y + v2.y)
def __sub__(self, v2):
return Vector2(self.x - v2.x, self.y - v2.y)
s1 = Vector2(2, 1)
s2 = Vector2(6, 3)
p = Vector2(2, 3)
print((p - s1).cross_prod(p - s2))Расстояние от точки до прямой
Площадь треугольника можно вычислить с помощью векторного произведения: \[ S=\frac{\left | \vec{AC} \times \vec{AB} \right |}{2} \] где \(A\), \(B\) и \(C\) - координаты вершин.
Кратчайшее расстояние \(d\) от точки \(p\) до прямой, проходящей через точки \(s_1\) и \(s_2\) можно вычислить по следующей формуле: \[ d=\frac{(s_1-p)\times (s_2-p)}{\left | s_2-s_1\right |} \]
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
class Vector2(Point):
def length(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
def cross_prod(self, v2):
return self.x * v2.y - self.y * v2.x
def __add__(self, v2):
return Vector2(self.x + v2.x, self.y + v2.y)
def __sub__(self, v2):
return Vector2(self.x - v2.x, self.y - v2.y)
s1 = Vector2(2, 1)
s2 = Vector2(6, 3)
p = Vector2(2, 3)
d = (s1 - p).cross_prod(s2 - p) / (s2-s1).length()
print(d)Площадь многоугольника
Для вычисления площади многоугольника можно использовать следующую формулу: \[ S=\frac{1}{2}\left | \sum_{i=1}^{n-1}(p_i\times p_{i+1})\right | \] Где \(p_1, p_2, ... , p_n\) - последовательно расположенные вершины многоугольника, при этом \(p_1=p_n\).
Проверка выпуклости многоугольника
Многоугольник является выпуклым, если для каждой прямой, проходящей через любую его вершину, все остальные вершины лежат в одной полуплоскости относительно прямой.
Определить выпуклость многоугольника можно с помощью векторного произведения векторов, образованных тремя последовательными вершинами.
Для выпуклого многоугольника знак векторного произведения должен быть одинаковым при обходе всех троек вершин.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
class Vector2(Point):
def cross_prod(self, v2):
return self.x * v2.y - self.y * v2.x
def __add__(self, v2):
return Vector2(self.x + v2.x, self.y + v2.y)
def __sub__(self, v2):
return Vector2(self.x - v2.x, self.y - v2.y)
p = [Vector2(1, 3), Vector2(3, 5),
Vector2(5, 4), Vector2(5, 2),
Vector2(2, 1), Vector2(1, 3)]
for i in range(len(p) - 2):
v = (p[i] - p[i+1]).cross_prod(p[i+1] - p[i+2])
print(v)