diff --git a/clitools/generators/redilysis_particles.py b/clitools/generators/redilysis_particles.py new file mode 100755 index 0000000..59e775a --- /dev/null +++ b/clitools/generators/redilysis_particles.py @@ -0,0 +1,288 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +v0.1.0 + + +LICENCE : CC + +by cocoa + +''' +from __future__ import print_function +import math +import random +import sys +import os +import time +import redis +import ast +import argparse + + +MAX_PARTICLES = 50 +MAX_TIME = 500 + +argsparser = argparse.ArgumentParser(description="Dummy generator") +argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) +argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output") +# Redis Args +argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str) +argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str) +# +argsparser.add_argument("-M","--max-particles",help="Max Particles. Default:{}".format(MAX_PARTICLES),default=MAX_PARTICLES,type=int) +argsparser.add_argument("-m","--max-time",help="Max Particles. Default:{}".format(MAX_TIME),default=MAX_TIME,type=int) + + +args = argsparser.parse_args() +verbose = args.verbose +ip = args.ip +port = args.port +max_particles = args.max_particles +max_time = args.max_time + +def debug(*args, **kwargs): + if( verbose == False ): + return + print(*args, file=sys.stderr, **kwargs) + + +def rgb2int(rgb): + #debug(name,"::rgb2int rbg:{}".format(rgb)) + return int('0x%02x%02x%02x' % tuple(rgb),0) + +def spectrum_120( ): + return ast.literal_eval(redisData["spectrum_10"]) + + +def rgb2int(rgb): + #debug(name,"::rgb2int rbg:{}".format(rgb)) + return int('0x%02x%02x%02x' % tuple(rgb),0) + +def msNow(): + return time.time() + +def refreshRedis(): + global redisData + for key in redisKeys: + redisData[key] = ast.literal_eval(r.get(key).decode('ascii')) + +name="generator::redilisys_particles" + +class UnpreparedParticle(Exception): + pass + +class Particle(object): + def __init__(self, x, y, m): + self.x = x + self.y = y + self.m = m + self.dx = 0 + self.dy = 0 + self.connectedTo = [] + + self.decay = random.randint(10,max_time) + self.color = (random.randint(128,256) - int(12.8 * self.m), + random.randint(128,256) - int(12.8 * self.m), + random.randint(128,256) - int(12.8 * self.m)) + self.color = (255,255,255) + #debug( self.color ) + + def interact(self, bodies): + self.connectedTo = [] + spec = redisData["spectrum_10"] + power = int(sum(spec[4:6])) + for other in bodies: + if other is self: + continue + dx = other.x - self.x + dy = other.y - self.y + dist = math.sqrt(dx*dx + dy*dy) + if dist == 0: + dist = 1 + if dist < 100 and random.randint(0,power) > 0.5 : + self.connectedTo.append(other) + self.decay += 2 + factor = other.m / dist**2 + high_power = sum(spec[8:9]) if sum(spec[8:9]) != 0 else 0.01 + self.dx += (dx * factor * self.m) + self.dy += (dy * factor * self.m) + #print "factor %f" % (factor,) + + def move(self): + spec = redisData["spectrum_10"] + x_friction = (2.2-(1+spec[7]/2)) + y_friction = (2.2-(1+spec[7]/2)) + #x_friction = 1.02 + #y_friction = 1.04 + self.dx /= x_friction if x_friction != 0 else 0.01 + self.dy /= y_friction if y_friction != 0 else 0.01 + self.x += self.dx + self.y += self.dy + if self.x > max_width: + self.dx = - self.dx /8 + self.x = max_width + if self.x < 1: + self.dx = - self.dx /8 + self.x = 1 + if self.y > max_height: + self.dy = - self.dy /4 + self.y = max_height + if self.y < 1: + self.dy = - self.dy /4 + self.y = 1 + #print "(%.2f,%.2f) -> (%.2f,%.2f)" % (ox, oy, self.x, self.y) + + def attractor(self,attractor): + spec = redisData["spectrum_10"] + power = sum(spec[0:4])/3 + # If we're going in the direction of center, reverse + next_x = self.x + self.dx + next_y = self.y + self.dy + next_dx = attractor["x"] - self.x + next_dy = attractor["y"] - self.y + next_dist = math.sqrt(next_dx*next_dx + next_dy*next_dy) + + dx = attractor["x"] - self.x + dy = attractor["y"] - self.y + dist = math.sqrt(dx*dx + dy*dy) + if dist == 0: + dist = 1 + factor = power/ dist**2 + x_acceleration = (dx * factor * power * power) + y_acceleration = (dx * factor * power * power) + + + if next_dist > dist: + self.dx -= x_acceleration * power + self.dy -= y_acceleration * power + else: + self.dx += x_acceleration + self.dy += y_acceleration + + +class Attractor(Particle): + def move(self): + pass + + +class ParticleViewer(object): + def __init__(self, particles, size=(800,800)): + (self.width, self.height) = size + self.size = size + self.particles = particles + self.xoff = 0 + self.yoff = 0 + self.scalefactor = 1 + + def redraw(self): + + pl = [] + drawnVectors = [] + for p in self.particles: + x = int(self.scalefactor * p.x) - self.xoff + y = int(self.scalefactor * p.y) - self.yoff + if x > max_width: + x = max_width + if x < 1: + x = 1 + if y > max_height: + y = max_height + if y < 1: + y = 1 + + color = rgb2int(p.color) + pl.append([x+1,y+1,0]) + pl.append([x+1,y+1,color]) + pl.append([x,y,color]) + + for other in p.connectedTo: + + if [other,self] in drawnVectors: + continue + drawnVectors.append([other,self]) + pl.append([x,y,0]) + pl.append([x,y,color]) + pl.append([other.x,other.y,color]) + + print(pl,flush = True) + + def decayParticles(self): + for i,p in enumerate(self.particles): + # Handle positional decay + if p.decay == 0: + del self.particles[i] + continue + p.decay = p.decay - 1 + # Handle color decay + n = int(255 * (p.decay / max_time )) + p.color = (n,n,n) + + + def emitParticles(self): + spec = redisData["spectrum_10"] + power = sum(spec[6:]) + if len(self.particles ) > math.sqrt(max_particles): + if len(self.particles) > max_particles: + return + if random.random() > power: + return + # x is either left or right + d = 600 + rx = 100 if random.randint(0,1) else 700 + #rx = random.randint(1,max_width) + ry = random.randint(1,max_height) + spec = redisData["spectrum_10"] + m = random.randint(1,1+int(10*spec[7])) + particles.append(Particle(rx, ry, m)) + + + def tick(self): + self.decayParticles() + self.emitParticles() + for p in self.particles: + p.interact(self.particles) + p.attractor({ + "x":max_width/2, + "y":max_height/2 + }) + for p in particles: + p.move() + self.redraw() + + def scale(self, factor): + self.scalefactor += factor + + + + +max_width = 800 +max_height = 800 +redisKeys = ["spectrum_120","spectrum_10"] +redisData = {} +redisLastHit = msNow() - 99999 +r = redis.Redis( + host=ip, + port=port) + +white = 16777215 + +refreshRedis() +if __name__ == "__main__": + particles = [] +# particles.append(Attractor(320, 200, 10)) +# particles.append(Attractor(100, 100, 10)) + + win = ParticleViewer(particles) + try: + while True: + win.tick() + refreshRedis() + time.sleep(.03) + + except KeyboardInterrupt: + pass