Guest User

Untitled

a guest
May 20th, 2018
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.56 KB | None | 0 0
  1. def get_filled_path(points):
  2. from OpenGL.GLU import gluNewTess, gluTessNormal, gluTessProperty,\
  3. gluTessBeginPolygon, gluTessBeginContour, gluTessEndContour,\
  4. gluTessEndPolygon, gluTessCallback, gluErrorString, gluTessVertex,\
  5. GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO, GLU_TESS_VERTEX,\
  6. GLU_TESS_BEGIN, GLU_TESS_END, GLU_TESS_ERROR, GLU_TESS_COMBINE
  7.  
  8. tess = gluNewTess()
  9. gluTessNormal(tess, 0, 0, 1)
  10. gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO)
  11.  
  12. tess_list = []
  13. tess_style = None
  14. tess_shape = None
  15.  
  16. def tess_vertex(vertex):
  17. global tess_shape
  18. tess_shape += list(vertex[0:2])
  19.  
  20. def tess_begin(which):
  21. global tess_style, tess_shape
  22. tess_style = which
  23. tess_shape = []
  24.  
  25. def tess_end():
  26. global tess_style, tess_shape
  27. tess_list.append((tess_style, tess_shape))
  28.  
  29. def tess_error(code):
  30. err = gluErrorString(code)
  31. pymt.pymt_logger.warning('BezierPath: GLU Tesselation Error: %s' % str(err))
  32.  
  33. gluTessCallback(tess, GLU_TESS_VERTEX, tess_vertex)
  34. gluTessCallback(tess, GLU_TESS_BEGIN, tess_begin)
  35. gluTessCallback(tess, GLU_TESS_END, tess_end)
  36. gluTessCallback(tess, GLU_TESS_ERROR, tess_error)
  37.  
  38. gluTessBeginPolygon(tess, None)
  39. gluTessBeginContour(tess)
  40. for x, y in zip(points[::2], points[1::2]):
  41. v_data = (x, y, 0)
  42. gluTessVertex(tess, v_data, v_data)
  43. gluTessEndContour(tess)
  44. gluTessEndPolygon(tess)
  45.  
  46. return tess_list
  47.  
  48. def draw_filled_path(points):
  49. from OpenGL.GL import glVertex2f
  50. for style, points in points:
  51. with gx_begin(style):
  52. for x, y in zip(points[::2], points[1::2]):
  53. glVertex2f(x, y)
  54.  
  55. def point_inside_polygon(x, y, poly):
  56. n = len(poly)
  57. if n < 2:
  58. return False
  59. inside = False
  60. p1x, p1y = poly[0]
  61. for i in range(n+1):
  62. p2x,p2y = poly[i % n]
  63. if y > min(p1y,p2y):
  64. if y <= max(p1y,p2y):
  65. if x <= max(p1x,p2x):
  66. if p1y != p2y:
  67. xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
  68. if p1x == p2x or x <= xinters:
  69. inside = not inside
  70. p1x,p1y = p2x,p2y
  71. return inside
  72.  
  73. class Curve(object):
  74. def __init__(self, points=[], tension=0., precision=1., is_closed=False):
  75. self._points = points
  76. self._tension = tension
  77. self._is_closed = is_closed
  78. self._curve = []
  79. self._filledpath = None
  80. self._precision = precision
  81. self.update()
  82.  
  83. def update(self):
  84. p = self._points
  85. self._curve = []
  86. self._filledpath = None
  87. if len(self._points) < 2:
  88. return
  89. if len(self._points) == 2:
  90. p0, p1 = p
  91. self._curve = [p0[0], p0[1], p1[0], p1[1]]
  92. return
  93. n = len(p) - 1
  94. if self._is_closed:
  95. for i in xrange(n):
  96. if i == 0:
  97. o = self._curve_seg(p[n], p[0], p[1], p[2])
  98. elif i == (n - 1):
  99. o = self._curve_seg(p[n-2], p[n-1], p[n], p[0])
  100. else:
  101. o = self._curve_seg(p[i-1], p[i], p[i+1], p[i+2])
  102. self._curve += o
  103. self._curve += self._curve_seg(p[n-1], p[n], p[0], p[1])
  104. else:
  105. for i in xrange(n):
  106. if i == 0:
  107. o = self._curve_seg(p[0], p[0], p[1], p[2])
  108. elif i == (n - 1):
  109. o = self._curve_seg(p[n-2], p[n-1], p[n], p[n])
  110. else:
  111. o = self._curve_seg(p[i-1], p[i], p[i+1], p[i+2])
  112. self._curve += o
  113.  
  114. def _curve_seg(self, p0, p1, p2, p3):
  115. curve = []
  116. p = self._precision
  117. tension = self._tension
  118. x = 0.
  119. y = 0.
  120. xl = p1[0] - 1.
  121. yl = p1[1] - 1.
  122.  
  123. t = 0.
  124. f = 1.
  125. k = 1.1
  126.  
  127. m1x = (1 - tension) * (p2[0] - p0[0]) / 2.
  128. m2x = (1 - tension) * (p3[0] - p1[0]) / 2.
  129. m1y = (1 - tension) * (p2[1] - p0[1]) / 2.
  130. m2y = (1 - tension) * (p3[1] - p1[1]) / 2.
  131.  
  132. while t <= 1:
  133. x = (2 * t * t * t - 3 * t * t + 1) * p1[0] + \
  134. (t * t * t - 2 * t * t + t) * m1x + \
  135. (-2 * t * t * t + 3 * t * t) * p2[0] + \
  136. (t * t * t - t * t) * m2x
  137. y = (2 * t * t * t - 3 * t * t + 1) * p1[1] + \
  138. (t * t * t - 2 * t * t + t) * m1y + \
  139. (-2 * t * t * t + 3 * t * t) * p2[1] + \
  140. (t * t * t - t * t) * m2y
  141.  
  142. #x = round(x)
  143. #y = round(y)
  144.  
  145. if x != xl or y != yl:
  146. if x - xl > p or y - yl > p or xl - x > p or yl - y > p:
  147. t -= f
  148. f = f / k
  149. else:
  150. curve += [x, y]
  151. xl = x
  152. yl = y
  153. if t + f > 1.:
  154. t = 1 - f
  155. else:
  156. f = f * k
  157. t += f
  158. return curve
  159.  
  160. @property
  161. def curve(self):
  162. return self._curve
  163.  
  164. @property
  165. def filledpath(self):
  166. if self._filledpath is None:
  167. self._filledpath = get_filled_path(self.curve)
  168. return self._filledpath
  169.  
  170. def _set_tension(self, value):
  171. if self._tension == value:
  172. return
  173. self._tension = value
  174. self.update()
  175. def _get_tension(self):
  176. return self._tension
  177. tension = property(_get_tension, _set_tension)
  178.  
  179. def _set_points(self, value):
  180. if self._points == value:
  181. return
  182. self._points = value
  183. self.update()
  184. def _get_points(self):
  185. return self._points
  186. points = property(_get_points, _set_points)
  187.  
  188. def _set_precision(self, value):
  189. if self._precision == value:
  190. return
  191. self._precision = value
  192. self.update()
  193. def _get_precision(self):
  194. return self._precision
  195. precision = property(_get_precision, _set_precision)
  196.  
  197. def _set_is_closed(self, value):
  198. if self._is_closed == value:
  199. return
  200. self._is_closed = value
  201. self.update()
  202. def _get_is_closed(self):
  203. return self._is_closed
  204. is_closed = property(_get_is_closed, _set_is_closed)
  205.  
  206.  
  207. if __name__ == '__main__':
  208. from pymt import *
  209.  
  210. w = getWindow()
  211.  
  212. class Shape(MTWidget):
  213. def __init__(self, **kwargs):
  214. super(Shape, self).__init__(**kwargs)
  215. self.curve = Curve(precision=10)
  216. def r():
  217. import random
  218. if random.random() > .5:
  219. return .5
  220. return .3
  221. self.color = map(lambda x: r(), xrange(3)) + [.5]
  222. self.linecolor = self.color[:3] + [.7]
  223. self.circlecolor = map(lambda x: x + .1, self.color[:3])
  224.  
  225. def collide_point(self, x, y):
  226. return point_inside_polygon(x, y, self.curve.points)
  227.  
  228. def draw(self):
  229. c = self.curve
  230. if c.is_closed:
  231. set_color(*self.color)
  232. draw_filled_path(c.filledpath)
  233. set_color(*self.linecolor)
  234. drawLine(c.curve, width=5.)
  235. set_color(*self.circlecolor)
  236. for p in c.points:
  237. drawCircle(pos=p, radius=3)
  238.  
  239. def on_touch_down(self, touch):
  240. if not self.collide_point(*touch.pos):
  241. return
  242. touch.grab(self)
  243. touch.userdata['controlpoints'] = []
  244. for idx in xrange(len(self.curve.points)):
  245. x, y = self.curve.points[idx]
  246. if Vector(x, y).distance(touch.pos) < 150:
  247. touch.userdata['controlpoints'].append(idx)
  248. return True
  249.  
  250. def on_touch_move(self, touch):
  251. if touch.grab_current != self:
  252. return
  253. if touch.dpos == (0, 0):
  254. return
  255. p = self.curve.points
  256. for idx in touch.userdata['controlpoints']:
  257. d = Vector(touch.pos) - Vector(touch.dpos)
  258. p[idx] = Vector(p[idx]) + d
  259. self.curve.update()
  260. return True
  261.  
  262.  
  263. class Canvas(MTWidget):
  264. def __init__(self, **kwargs):
  265. super(Canvas, self).__init__(**kwargs)
  266.  
  267. def on_touch_down(self, touch):
  268. if super(Canvas, self).on_touch_down(touch):
  269. return True
  270. shape = Shape()
  271. self.add_widget(shape)
  272. touch.userdata['shape'] = shape
  273. shape.curve.points = shape.curve.points + [touch.pos]
  274. shape.curve.points = shape.curve.points + [touch.pos]
  275. return True
  276.  
  277. def on_touch_move(self, touch):
  278. if 'shape' in touch.userdata:
  279. shape = touch.userdata['shape']
  280. last = shape.curve.points[-2]
  281. if Vector(touch.pos).distance(Vector(last)) > 80:
  282. shape.curve.points = shape.curve.points + [touch.pos]
  283. else:
  284. shape.curve.points = shape.curve.points[:-1] + [touch.pos]
  285. return True
  286. return super(Canvas, self).on_touch_move(touch)
  287.  
  288. def on_touch_up(self, touch):
  289. if 'shape' in touch.userdata:
  290. shape = touch.userdata['shape']
  291. if len(shape.curve.curve) < 3:
  292. self.remove_widget(shape)
  293. return
  294. shape.curve.is_closed = True
  295. shape.curve.update()
  296. return True
  297. return super(Canvas, self).on_touch_up(touch)
  298.  
  299.  
  300. runTouchApp(Canvas())
Add Comment
Please, Sign In to add comment