You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

redilysis_particles.py 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. # -*- mode: Python -*-
  4. '''
  5. v0.1.0
  6. LICENCE : CC
  7. by cocoa
  8. '''
  9. from __future__ import print_function
  10. import math
  11. import random
  12. import sys
  13. import os
  14. import time
  15. import redis
  16. import ast
  17. import argparse
  18. MAX_PARTICLES = 50
  19. MAX_TIME = 500
  20. argsparser = argparse.ArgumentParser(description="Dummy generator")
  21. argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
  22. argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
  23. # Redis Args
  24. argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
  25. argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
  26. #
  27. argsparser.add_argument("-M","--max-particles",help="Max Particles. Default:{}".format(MAX_PARTICLES),default=MAX_PARTICLES,type=int)
  28. argsparser.add_argument("-m","--max-time",help="Max Particles. Default:{}".format(MAX_TIME),default=MAX_TIME,type=int)
  29. args = argsparser.parse_args()
  30. verbose = args.verbose
  31. ip = args.ip
  32. port = args.port
  33. max_particles = args.max_particles
  34. max_time = args.max_time
  35. def debug(*args, **kwargs):
  36. if( verbose == False ):
  37. return
  38. print(*args, file=sys.stderr, **kwargs)
  39. def rgb2int(rgb):
  40. #debug(name,"::rgb2int rbg:{}".format(rgb))
  41. return int('0x%02x%02x%02x' % tuple(rgb),0)
  42. def spectrum_120( ):
  43. return ast.literal_eval(redisData["spectrum_10"])
  44. def rgb2int(rgb):
  45. #debug(name,"::rgb2int rbg:{}".format(rgb))
  46. return int('0x%02x%02x%02x' % tuple(rgb),0)
  47. def msNow():
  48. return time.time()
  49. def refreshRedis():
  50. global redisData
  51. for key in redisKeys:
  52. redisData[key] = ast.literal_eval(r.get(key).decode('ascii'))
  53. name="generator::redilisys_particles"
  54. class UnpreparedParticle(Exception):
  55. pass
  56. class Particle(object):
  57. def __init__(self, x, y, m):
  58. self.x = x
  59. self.y = y
  60. self.m = m
  61. self.dx = 0
  62. self.dy = 0
  63. self.connectedTo = []
  64. self.decay = random.randint(10,max_time)
  65. self.color = (random.randint(128,256) - int(12.8 * self.m),
  66. random.randint(128,256) - int(12.8 * self.m),
  67. random.randint(128,256) - int(12.8 * self.m))
  68. self.color = (255,255,255)
  69. #debug( self.color )
  70. def interact(self, bodies):
  71. self.connectedTo = []
  72. spec = redisData["spectrum_10"]
  73. power = int(sum(spec[4:6]))
  74. for other in bodies:
  75. if other is self:
  76. continue
  77. dx = other.x - self.x
  78. dy = other.y - self.y
  79. dist = math.sqrt(dx*dx + dy*dy)
  80. if dist == 0:
  81. dist = 1
  82. if dist < 100 and random.randint(0,power) > 0.5 :
  83. self.connectedTo.append(other)
  84. self.decay += 2
  85. factor = other.m / dist**2
  86. high_power = sum(spec[8:9]) if sum(spec[8:9]) != 0 else 0.01
  87. self.dx += (dx * factor * self.m)
  88. self.dy += (dy * factor * self.m)
  89. #print "factor %f" % (factor,)
  90. def move(self):
  91. spec = redisData["spectrum_10"]
  92. x_friction = (2.2-(1+spec[7]/2))
  93. y_friction = (2.2-(1+spec[7]/2))
  94. #x_friction = 1.02
  95. #y_friction = 1.04
  96. self.dx /= x_friction if x_friction != 0 else 0.01
  97. self.dy /= y_friction if y_friction != 0 else 0.01
  98. self.x += self.dx
  99. self.y += self.dy
  100. if self.x > max_width:
  101. self.dx = - self.dx /8
  102. self.x = max_width
  103. if self.x < 1:
  104. self.dx = - self.dx /8
  105. self.x = 1
  106. if self.y > max_height:
  107. self.dy = - self.dy /4
  108. self.y = max_height
  109. if self.y < 1:
  110. self.dy = - self.dy /4
  111. self.y = 1
  112. #print "(%.2f,%.2f) -> (%.2f,%.2f)" % (ox, oy, self.x, self.y)
  113. def attractor(self,attractor):
  114. spec = redisData["spectrum_10"]
  115. power = sum(spec[0:4])/3
  116. # If we're going in the direction of center, reverse
  117. next_x = self.x + self.dx
  118. next_y = self.y + self.dy
  119. next_dx = attractor["x"] - self.x
  120. next_dy = attractor["y"] - self.y
  121. next_dist = math.sqrt(next_dx*next_dx + next_dy*next_dy)
  122. dx = attractor["x"] - self.x
  123. dy = attractor["y"] - self.y
  124. dist = math.sqrt(dx*dx + dy*dy)
  125. if dist == 0:
  126. dist = 1
  127. factor = power/ dist**2
  128. x_acceleration = (dx * factor * power * power)
  129. y_acceleration = (dx * factor * power * power)
  130. if next_dist > dist:
  131. self.dx -= x_acceleration * power
  132. self.dy -= y_acceleration * power
  133. else:
  134. self.dx += x_acceleration
  135. self.dy += y_acceleration
  136. class Attractor(Particle):
  137. def move(self):
  138. pass
  139. class ParticleViewer(object):
  140. def __init__(self, particles, size=(800,800)):
  141. (self.width, self.height) = size
  142. self.size = size
  143. self.particles = particles
  144. self.xoff = 0
  145. self.yoff = 0
  146. self.scalefactor = 1
  147. def redraw(self):
  148. pl = []
  149. drawnVectors = []
  150. for p in self.particles:
  151. x = int(self.scalefactor * p.x) - self.xoff
  152. y = int(self.scalefactor * p.y) - self.yoff
  153. if x > max_width:
  154. x = max_width
  155. if x < 1:
  156. x = 1
  157. if y > max_height:
  158. y = max_height
  159. if y < 1:
  160. y = 1
  161. color = rgb2int(p.color)
  162. pl.append([x+1,y+1,0])
  163. pl.append([x+1,y+1,color])
  164. pl.append([x,y,color])
  165. for other in p.connectedTo:
  166. if [other,self] in drawnVectors:
  167. continue
  168. drawnVectors.append([other,self])
  169. pl.append([x,y,0])
  170. pl.append([x,y,color])
  171. pl.append([other.x,other.y,color])
  172. print(pl,flush = True)
  173. def decayParticles(self):
  174. for i,p in enumerate(self.particles):
  175. # Handle positional decay
  176. if p.decay == 0:
  177. del self.particles[i]
  178. continue
  179. p.decay = p.decay - 1
  180. # Handle color decay
  181. n = int(255 * (p.decay / max_time ))
  182. p.color = (n,n,n)
  183. def emitParticles(self):
  184. spec = redisData["spectrum_10"]
  185. power = sum(spec[6:])
  186. if len(self.particles ) > math.sqrt(max_particles):
  187. if len(self.particles) > max_particles:
  188. return
  189. if random.random() > power:
  190. return
  191. # x is either left or right
  192. d = 600
  193. rx = 100 if random.randint(0,1) else 700
  194. #rx = random.randint(1,max_width)
  195. ry = random.randint(1,max_height)
  196. spec = redisData["spectrum_10"]
  197. m = random.randint(1,1+int(10*spec[7]))
  198. particles.append(Particle(rx, ry, m))
  199. def tick(self):
  200. self.decayParticles()
  201. self.emitParticles()
  202. for p in self.particles:
  203. p.interact(self.particles)
  204. p.attractor({
  205. "x":max_width/2,
  206. "y":max_height/2
  207. })
  208. for p in particles:
  209. p.move()
  210. self.redraw()
  211. def scale(self, factor):
  212. self.scalefactor += factor
  213. max_width = 800
  214. max_height = 800
  215. redisKeys = ["spectrum_120","spectrum_10"]
  216. redisData = {}
  217. redisLastHit = msNow() - 99999
  218. r = redis.Redis(
  219. host=ip,
  220. port=port)
  221. white = 16777215
  222. refreshRedis()
  223. if __name__ == "__main__":
  224. particles = []
  225. # particles.append(Attractor(320, 200, 10))
  226. # particles.append(Attractor(100, 100, 10))
  227. win = ParticleViewer(particles)
  228. try:
  229. while True:
  230. win.tick()
  231. refreshRedis()
  232. time.sleep(.03)
  233. except KeyboardInterrupt:
  234. pass