Advertisement
Guest User

Untitled

a guest
Apr 25th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.79 KB | None | 0 0
  1. import math
  2. import itertools
  3. from operator import add
  4. from functools import reduce
  5.  
  6. import numpy as np
  7. from scipy import stats as st
  8. import matplotlib.pyplot as plt
  9.  
  10. class Vertex:
  11. def __init__(self,x,y):
  12. self.x=x
  13. self.y=y
  14.  
  15. def dot(self,b):
  16. return self.x*b.x + self.y*b.y
  17.  
  18. def angle_between(b,a):
  19. return np.arctan2(b.y,b.x) - np.arctan2(a.y,a.x)
  20. #theta = math.acos(a.dot(b)/(a.length()*b.length()))
  21. #if (a.x < b.x) ^ (a.y > b.y):
  22. # return theta
  23. #else:
  24. # return -theta
  25.  
  26. def angle(self):
  27. if self.x < 0:
  28. if self.y < 0:
  29. return (-math.pi) + (math.atan(self.y/self.x))
  30. else:
  31. return math.pi-math.atan(self.y/self.x)
  32. elif self.x == 0:
  33. return np.sign(self.y)*math.pi/2
  34. else:
  35. return math.atan(self.y/self.x)
  36.  
  37.  
  38. if self.x == 0:
  39. return 0
  40. return math.atan(self.y/self.x)
  41.  
  42. def __add__(a,b):
  43. x = a.x+b.x
  44. y = a.y+b.y
  45. return Vertex(x,y)
  46.  
  47. def __mul__(a,b):
  48. try:
  49. return Vertex(a.x*b, a.y*b)
  50. except:
  51. raise NotImplementedError
  52.  
  53. def __truediv__(a,b):
  54. try:
  55. return Vertex(a.x/b, a.y/b)
  56. except:
  57. raise NotImplementedError
  58.  
  59. def __sub__(a,b):
  60. x = a.x-b.x
  61. y = a.y-b.y
  62. return Vertex(x,y)
  63.  
  64. def __str__(self):
  65. return "({0},{1})".format(self.x,self.y)
  66.  
  67. def length(self):
  68. return math.sqrt(self.x**2+self.y**2)
  69.  
  70. def toarray(self):
  71. return np.array([self.x,self.y])
  72.  
  73. def which(v):
  74. return np.argmax([x is None for x in v])
  75.  
  76. class Triangle:
  77. def __init__(self, *, vertices, angles=[None,None,None], fuzzy=True):
  78. self.angles = np.array(angles)
  79. self.a1,self.a2,self.a3=self.angles
  80. self.v1,self.v2,self.v3=np.array(vertices)
  81. self.flag = which([self.v1,self.v2,self.v3])
  82. if self.flag == 0:
  83. self.vertices = [self.v1,self.v2,self.v3]
  84. elif self.flag == 1:
  85. self.vertices = [self.v2,self.v1,self.v3]
  86. self.angles = [self.a2,self.a1,self.a3]
  87. elif self.flag == 2:
  88. self.vertices = [self.v3,self.v2,self.v1]
  89. self.angles = [self.a3,self.a2,self.a1]
  90. self.vertices = np.array(self.vertices)
  91.  
  92.  
  93. # if we have two angles fill in the third
  94. if self.get_num_angles() == 2:
  95. self.fill_angle()
  96.  
  97. if self.get_num_vertices() == 3:
  98. # compute the angles between them
  99. self.fill_angles_from_vertices()
  100. elif self.get_num_vertices() == 2:
  101. if self.get_num_angles() > 0:
  102. # compute the remaining angles and vertices
  103. self.fill_missing_vertex()
  104. self.fill_angles_from_vertices
  105. else:
  106. raise Exception('Without all the vertices we need at least one angle.')
  107. else:
  108. if not fuzzy:
  109. raise Exception('Need at least two vertices to define a triangle.')
  110. else:
  111. for v in self.vertices:
  112. if v is not None:
  113. return v
  114. self.lengths()
  115.  
  116. def vertices(self):
  117. if self.flag == 0:
  118. return self.vertices
  119. elif self.flag == 1:
  120. return np.array([self.v2,self.v1,self.v3])
  121. elif self.flag == 2:
  122. return np.array([self.v3,self.v2,self.v1])
  123.  
  124. def angless(self):
  125. if self.flag == 0:
  126. return self.angles
  127. elif self.flag == 1:
  128. return np.array([self.a2,self.a1,self.a3])
  129. elif self.flag == 2:
  130. return np.array([self.a3,self.a2,self.a1])
  131.  
  132. def center(self):
  133. return reduce(add,self.vertices)/3
  134.  
  135. def get_num_angles(self):
  136. return np.sum(np.array([a != None for a in self.angles]))
  137.  
  138. def get_num_vertices(self):
  139. return np.sum(np.array([v != None for v in self.vertices]))
  140.  
  141. def fill_angles_from_vertices(self):
  142. if self.get_num_angles() == 3:
  143. return None
  144. which = np.array([a != None for a in self.angles])
  145. which_not = np.invert(which)
  146. index = np.argmax(which_not)
  147. which_not = np.setdiff1d(np.arange(0,3),[index])
  148.  
  149. side1 = self.vertices[index] - self.vertices[which_not[0]]
  150. side2 = self.vertices[index] - self.vertices[which_not[1]]
  151. self.angles[index] = side1.angle_between(side2)
  152. self.a1,self.a2,self.a3 = self.angles
  153. self.fill_angles_from_vertices()
  154.  
  155. def fill_missing_vertex(self):
  156. # find missing vertex
  157. which = np.array([a != None for a in self.vertices])
  158. which_not = np.invert(which)
  159. index = np.argmax(which_not)
  160. which_not = np.setdiff1d(np.arange(0,3),[index])
  161.  
  162. va = self.vertices[which_not[0]]
  163. ab = self.angles[which_not[0]]
  164. vb = self.vertices[which_not[1]]
  165. aa = self.angles[which_not[1]]
  166. ac = self.angles[index]
  167.  
  168. # sin rule
  169. C = vb - va
  170. vC = (vb - va).length()
  171. vA = (vC/math.sin(ac)) * math.sin(aa)
  172.  
  173. adj = C.angle() # rotation so angle is relative to side C
  174. A = Vertex(vA*math.cos((ab)+adj), vA*math.sin(ab+adj))
  175. if self.flag == 0:
  176. A = A
  177. elif self.flag == 1:
  178. A = Vertex(-A.x,-A.y)
  179. elif self.flag == 2:
  180. A = Vertex(-A.y,-A.x)
  181. self.vertices[index] = va + A
  182. self.v1,self.v2,self.v3 = self.vertices
  183. return None
  184.  
  185. def fill_angle(self):
  186. which = np.array([a != None for a in self.angles])
  187. if np.all(which):
  188. return
  189. elif sum(which) < 2:
  190. raise Exception('Need at least two angles.')
  191. else:
  192. if np.sum(self.angles[which]) > math.pi:
  193. raise Exception('Angles must add up to < π radians')
  194. self.angles[np.invert(which)] = math.pi - np.sum(self.angles[which])
  195. self.a1,self.a2,self.a3 = self.angles
  196. return None
  197.  
  198. def lengths(self):
  199. self.l1 = (self.v2 - self.v3).length()
  200. self.l2 = (self.v3 - self.v1).length()
  201. self.l3 = (self.v1 - self.v2).length()
  202.  
  203. def __str__(self):
  204. string = '''
  205. Angles: {a1}, {a2}, {a3}
  206. Vertices: {v1}, {v2}, {v3}
  207. Lengths: {l1}, {l2}, {l3}
  208. '''.format(
  209. a1=math.degrees(self.a1), a2=math.degrees(self.a2), a3=math.degrees(self.a3),
  210. v1=self.v1, v2=self.v2, v3=self.v3,
  211. l1=self.l1, l2=self.l2, l3=self.l3
  212. )
  213. return string
  214.  
  215. def plot(t,marker='.',fig=None):
  216. if fig is None:
  217. fig,ax = plt.subplots(1,1,figsize=(5,5))
  218. else:
  219. ax = fig.axes[0]
  220. ax.scatter(t.v1.x,t.v1.y,label='v1',marker=marker)
  221. ax.scatter(t.v2.x,t.v2.y,label='v2',marker=marker)
  222. try:
  223. ax.scatter(t.v3.x,t.v3.y,label='v3',marker=marker)
  224. except:
  225. None
  226. try:
  227. None
  228. #center = t.center()
  229. #ax.scatter(center.x,center.y,label='center',marker='x')
  230. except:
  231. None
  232.  
  233. mmax = max(ax.get_xlim()[1],ax.get_ylim()[1])
  234. plt.xlim(0,mmax)
  235. plt.ylim(0,mmax)
  236. plt.legend(loc=3)
  237. return fig
  238.  
  239. def ArrayVertex(A):
  240. if (A[0] < 0) or (A[1] < 0):
  241. return None
  242. return Vertex(A[0],A[1])
  243.  
  244. def vertices_from_arrays(led1,led2,led3):
  245. return [(ArrayVertex(led1[t,:]),ArrayVertex(led2[t,:]),ArrayVertex(led3[t,:]))
  246. for t in np.arange(np.shape(led1)[0])]
  247.  
  248. def triangles_from_vertex_arrays(led1,led2,led3):
  249. return [Triangle(vertices=v) for v in vertices_from_arrays(led1,led2,led3)]
  250.  
  251. class TriangleSet:
  252. def __init__(self,led1,led2,led3,central_tendancy='mean'):
  253. self.triangles = triangles_from_vertex_arrays(led1,led2,led3)
  254. self.central_tendancy=central_tendancy
  255.  
  256. def all_angles(self):
  257. return [t.angless() for t in self.triangles]
  258.  
  259. def mean_angle(self):
  260. if self.central_tendancy=='mean':
  261. return np.mean(self.all_angles(),axis=0)
  262. elif self.central_tendancy=='median':
  263. return np.median(self.all_angles(),axis=0)
  264. elif self.central_tendancy=='r_mean':
  265. r = 1.5
  266. return np.array([np.mean(st.sigmaclip([(t[i])
  267. for t in self.all_angles()],r,r)[0])
  268. for i in range(3)])
  269.  
  270. def apply(self,vertices):
  271. #try:
  272. return Triangle(vertices=vertices, angles=self.mean_angle())
  273. #except:
  274. # None
  275.  
  276. def apply_to_set(self,led1,led2,led3):
  277. return [self.apply(v) for v in vertices_from_arrays(led1,led2,led3)]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement