import numpy.linalg
import numpy.random
from matplotlib import pyplot as plt
import numpy as np
import matplotlib.path as path
from math import pi, cos, sin, atan, asin, fabs, sqrt
def ellipse_by_5_points(p):
A = [[p[0][0] * p[0][1], p[0][1] * p[0][1], p[0][0], p[0][1], 1],
[p[1][0] * p[1][1], p[1][1] * p[1][1], p[1][0], p[1][1], 1],
[p[2][0] * p[2][1], p[2][1] * p[2][1], p[2][0], p[2][1], 1],
[p[3][0] * p[3][1], p[3][1] * p[3][1], p[3][0], p[3][1], 1],
[p[4][0] * p[4][1], p[4][1] * p[4][1], p[4][0], p[4][1], 1]]
B = [[p[0][0] * p[0][0], p[0][1] * p[0][1], p[0][0], p[0][1], 1],
[p[1][0] * p[1][0], p[1][1] * p[1][1], p[1][0], p[1][1], 1],
[p[2][0] * p[2][0], p[2][1] * p[2][1], p[2][0], p[2][1], 1],
[p[3][0] * p[3][0], p[3][1] * p[3][1], p[3][0], p[3][1], 1],
[p[4][0] * p[4][0], p[4][1] * p[4][1], p[4][0], p[4][1], 1]]
C = [[p[0][0] * p[0][0], p[0][0] * p[0][1], p[0][0], p[0][1], 1],
[p[1][0] * p[1][0], p[1][0] * p[1][1], p[1][0], p[1][1], 1],
[p[2][0] * p[2][0], p[2][0] * p[2][1], p[2][0], p[2][1], 1],
[p[3][0] * p[3][0], p[3][0] * p[3][1], p[3][0], p[3][1], 1],
[p[4][0] * p[4][0], p[4][0] * p[4][1], p[4][0], p[4][1], 1]]
D = [[p[0][0] * p[0][0], p[0][0] * p[0][1], p[0][1] * p[0][1], p[0][1], 1],
[p[1][0] * p[1][0], p[1][0] * p[1][1], p[1][1] * p[1][1], p[1][1], 1],
[p[2][0] * p[2][0], p[2][0] * p[2][1], p[2][1] * p[2][1], p[2][1], 1],
[p[3][0] * p[3][0], p[3][0] * p[3][1], p[3][1] * p[3][1], p[3][1], 1],
[p[4][0] * p[4][0], p[4][0] * p[4][1], p[4][1] * p[4][1], p[4][1], 1]]
E = [[p[0][0] * p[0][0], p[0][0] * p[0][1], p[0][1] * p[0][1], p[0][0], 1],
[p[1][0] * p[1][0], p[1][0] * p[1][1], p[1][1] * p[1][1], p[1][0], 1],
[p[2][0] * p[2][0], p[2][0] * p[2][1], p[2][1] * p[2][1], p[2][0], 1],
[p[3][0] * p[3][0], p[3][0] * p[3][1], p[3][1] * p[3][1], p[3][0], 1],
[p[4][0] * p[4][0], p[4][0] * p[4][1], p[4][1] * p[4][1], p[4][0], 1]]
F = [[p[0][0] * p[0][0], p[0][0] * p[0][1], p[0][1] * p[0][1], p[0][0], p[0][1]],
[p[1][0] * p[1][0], p[1][0] * p[1][1], p[1][1] * p[1][1], p[1][0], p[1][1]],
[p[2][0] * p[2][0], p[2][0] * p[2][1], p[2][1] * p[2][1], p[2][0], p[2][1]],
[p[3][0] * p[3][0], p[3][0] * p[3][1], p[3][1] * p[3][1], p[3][0], p[3][1]],
[p[4][0] * p[4][0], p[4][0] * p[4][1], p[4][1] * p[4][1], p[4][0], p[4][1]]]
a = numpy.linalg.det(A)
b = -numpy.linalg.det(B)
c = numpy.linalg.det(C)
d = -numpy.linalg.det(D)
e = numpy.linalg.det(E)
f = -numpy.linalg.det(F)
# I1 = a + c
# I2 = a * c - (b / 2) ** 2
# I3 = numpy.linalg.det([[a, b / 2, d / 2], [b / 2, c, e / 2], [d / 2, e / 2, f]])
#
# if I2 > 0 and I1 * I3 < 0:
# return [a, b, c, d, e, f]
# else:
# return None
return [a, b, c, d, e, f]
def rotate(A, B, C):
return (B[0] - A[0]) * (C[1] - B[1]) - (B[1] - A[1]) * (C[0] - B[0])
def jarvismarch(A):
n = len(A)
P = [i for i in range(n)]
for i in range(1, n):
if A[P[i]][0] < A[P[0]][0]:
P[i], P[0] = P[0], P[i]
H = [P[0]]
del P[0]
P.append(H[0])
while True:
right = 0
for i in range(1, len(P)):
if rotate(A[H[-1]], A[P[right]], A[P[i]]) < 0:
right = i
if P[right] == H[0]:
break
else:
H.append(P[right])
del P[right]
H = [A[H[i]] for i in range(len(H))]
return H
def in_ellipse(p, koef):
if koef[0] * p[0] ** 2 + koef[1] * p[0] * p[1] + koef[2] * p[1] ** 2 + koef[3] * p[0] + koef[4] * p[1] + koef[5] < 0:
print(p)
return True
return False
def empty_ellipse(koefficient, points, ii):
for i in points:
if i not in ii:
if in_ellipse(i, koefficient):
return False
return True
def create_points(N):
points = []
while len(points) < N:
new_p = [numpy.random.randint(-10, 10), numpy.random.randint(-10, 10)]
if new_p not in points:
points.append(new_p)
return points
def empty_ellipses_into_5_points(points):
empty_ellipses = []
e_numbers = []
for i1 in range(len(points)):
for i2 in range(i1 + 1, len(points)):
for i3 in range(i2 + 1, len(points)):
for i4 in range(i3 + 1, len(points)):
for i5 in range(i4 + 1, len(points)):
conv = jarvismarch([points[i1], points[i2], points[i3], points[i4], points[i5]])
if (len(conv) == 5):
koefficient = ellipse_by_5_points(conv)
if empty_ellipse(koefficient, points,[points[i1], points[i2], points[i3], points[i4], points[i5]]):
empty_ellipses.append(koefficient)
e_numbers.append([i1, i2, i3, i4, i5])
return empty_ellipses, e_numbers
def draw_ellipse(ellipse):
a = ellipse[0]
b = ellipse[1]
c = ellipse[2]
d = ellipse[3]
e = ellipse[4]
f = ellipse[5]
matrix = np.mat([[c, b / 2], [b / 2, a]])
w, ww = np.linalg.eig(matrix)
ww = np.squeeze(np.asarray(ww))
y0 = (d * b - 2 * a * e) / (4 * a * c - b * b) # y-position of the center
x0 = -(e + 2 * c * y0) / b # x-position of the center
k = ww[0][1] / ww[0][0]
k1 = ww[1][1] / ww[1][0]
r_2 = a * x0 * x0 + b * x0 * y0 + c * y0 * y0 - f
delta_x = r_2 / (a + b * k + c * k * k)
delta_y = k * k * delta_x
ax = sqrt(delta_x + delta_y)
delta_x = r_2 / (a + b * k1 + c * k1 * k1)
delta_y = k1 * k1 * delta_x
by = sqrt(delta_x + delta_y)
t_rot = atan(k) # rotation angle
t = np.linspace(0, 2 * pi, 100)
Ell = np.array([ax * np.cos(t), by * np.sin(t)])
R_rot = np.array([[cos(t_rot), -sin(t_rot)], [sin(t_rot), cos(t_rot)]])
Ell_rot = np.zeros((2, Ell.shape[1]))
for i in range(Ell.shape[1]):
Ell_rot[:, i] = np.dot(R_rot, Ell[:, i])
plt.plot(x0 + Ell_rot[0, :], y0 + Ell_rot[1, :], 'darkorange') # rotated ellipse
# return [b / (2 * a), c / a]
points = create_points(7)
print(points)
empty_ellipses, e_numbers = empty_ellipses_into_5_points(points)
k = 0
for i in points:
plt.plot(i[0], i[1], 'bo')
plt.annotate(str("%d" % k), [i[0], i[1]])
k = k + 1
plt.grid()
plt.axis([-11, 11, -11, 11], 'equal')
plt.gca().set_aspect("equal")
plt.show()
for ellipse in empty_ellipses:
k = 0
for i in points:
plt.plot(i[0], i[1], 'bo')
plt.annotate(str("%d" % k), [i[0], i[1]])
k = k + 1
plt.grid()
plt.axis([-11, 11, -11, 11], 'equal')
plt.gca().set_aspect("equal")
draw_ellipse(ellipse)
plt.show()
#plt.savefig('/home/kate/Рабочий стол/Figure_1.png')