[init]
This commit is contained in:
commit
6d70ca0c32
39 changed files with 13735 additions and 0 deletions
2407
generators/159.gml
Executable file
2407
generators/159.gml
Executable file
File diff suppressed because it is too large
Load diff
2791
generators/160.gml
Executable file
2791
generators/160.gml
Executable file
File diff suppressed because it is too large
Load diff
2873
generators/OSC3.py
Normal file
2873
generators/OSC3.py
Normal file
File diff suppressed because it is too large
Load diff
53
generators/blank.py
Executable file
53
generators/blank.py
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Send only black points
|
||||
v0.1.0
|
||||
|
||||
Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
name="generator::dummy"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
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")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
|
||||
shape = [[400,400,0],[400,400,64],[400,400,0]]
|
||||
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
BIN
generators/book2.ild
Executable file
BIN
generators/book2.ild
Executable file
Binary file not shown.
54
generators/brmlab1.svg
Executable file
54
generators/brmlab1.svg
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xml:space="preserve"
|
||||
height="53"
|
||||
width="299.96875"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="brmlab1.svg"
|
||||
inkscape:export-filename="/home/prusnak/work/scm/laserdisplay/svglaser/templates/template3.svg.png"
|
||||
inkscape:export-xdpi="200"
|
||||
inkscape:export-ydpi="200"><defs
|
||||
id="defs2988" /><metadata
|
||||
id="metadata78"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="689"
|
||||
id="namedview76"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-2.5851173"
|
||||
inkscape:cy="-55.600814"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-global="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
id="path20"
|
||||
style="fill:none;stroke:#000000;stroke-opacity:1"
|
||||
d="m 137.17375,22.4425 c 0,-1.815 5.24,-4.345 13.73375,-4.345 3.94875,0 7.73,0.59 10.37875,1.62 2.085,0.81125 3.32875,1.83 3.32875,2.725 0,9.0725 0.0188,30.05375 0.0188,30.05375 l 5.87245,-0.004 c 0,-10e-4 -0.0175,-20.97875 -0.0175,-30.05 0,-2.035 -0.9175,-5.805 -7.0725,-8.2 -3.35125,-1.3025 -7.7925,-2.01875 -12.50875,-2.01875 -4.71625,0 -9.15875,0.71625 -12.50875,2.01875 -1.7975,0.7 -3.16375,1.50625 -4.175,2.3625 -1.01,-0.8475 -2.3675,-1.66875 -4.15,-2.3625 -3.34875,-1.3025 -7.79125,-2.01875 -12.50875,-2.01875 -4.715,0 -9.15625,0.71625 -12.50625,2.01875 -6.15625,2.395 -7.075,6.165 -7.075,8.2 0,9.8775 -0.0163,30.04875 -0.0163,30.04875 l 5.87375,0.005 c 0,0 0.0175,-20.17375 0.0175,-30.05375 0,-1.815 5.215,-4.345 13.70625,-4.345 3.94875,0 7.73125,0.59 10.38,1.62 2.08375,0.81125 3.32875,1.83 3.32875,2.725 0,9.0725 0.0175,30.0575 0.0175,30.0575 l 5.87375,-0.005 c 0,0 0.009,-20.98125 0.009,-30.0525 M 93.61125,18.3922 c -1.0075,-1.47125 -2.7675,-2.98 -5.79125,-4.15625 -3.35,-1.3025 -7.79375,-2.02 -12.50875,-2.02 -4.715,0 -9.15875,0.7175 -12.5075,2.02 C 56.64875,16.63 55.73,20.4 55.73,22.435 c 0,9.87875 -0.0175,30.04875 -0.0175,30.04875 l 5.87375,0.005 c 0,0 0.0175,-20.17375 0.0175,-30.05375 0,-1.81375 5.21375,-4.345 13.7075,-4.345 3.9475,0 7.73,0.59 10.37875,1.62125 1.58875,0.6175 2.6875,1.355 3.1225,2.0675 l 4.79875,-3.38625 z m 86.2125,34.1 5.874,0 0,-52.0075 -5.874,0 0,52.0075 z m 24.45,-33.325 c -0.89625,0 -1.91375,1.24375 -2.725,3.32875 -1.03,2.64875 -1.62125,6.43125 -1.62125,10.37875 0,8.4925 2.53125,13.7075 4.34625,13.7075 7.19625,0 24.94,0.0225 31.975,0.0313 l 0,-27.44625 -31.975,0 z m 37.84875,33.32875 -2.94,-0.004 c 0,0 -25.83625,-0.035 -34.90875,-0.035 -2.035,0 -5.80625,-0.91875 -8.2,-7.07375 -1.3025,-3.35125 -2.02,-7.7925 -2.02,-12.50875 0,-4.715 0.7175,-9.1575 2.02,-12.5075 2.39375,-6.155 6.165,-7.075 8.2,-7.075 l 34.9125,0 2.91979,0.006 0.0165,39.198 z m 49.85125,-9.24125 c -0.80875,2.085 -1.82875,3.32875 -2.7225,3.32875 -7.1975,0 -24.94125,0.0225 -31.97625,0.0313 l 0,-27.4475 31.97625,0.001 c 1.81375,0 4.345,5.215 4.345,13.7075 0,3.94625 -0.5925,7.73 -1.6225,10.37875 M 297.45,20.3687 c -2.39375,-6.155 -6.165,-7.075 -8.19875,-7.075 l -31.97625,-0.002 0,-12.80625 -5.87375,0 0,52.0125 2.94125,-0.004 c 0,0 25.83625,-0.0362 34.90875,-0.0362 2.03375,0 5.805,-0.9175 8.19875,-7.0725 1.30375,-3.35125 2.02,-7.7925 2.02,-12.50875 0,-4.715 -0.71625,-9.1575 -2.02,-12.5075 M 41.07375,43.255 c -0.80875,2.085 -1.82875,3.32875 -2.725,3.32875 -7.195,0 -24.94,0.0225 -31.97375,0.0313 l 0,-27.4475 31.97375,0.001 c 1.815,0 4.34625,5.215 4.34625,13.7075 0,3.94625 -0.5925,7.73 -1.62125,10.37875 m 5.475,-22.88625 c -2.39375,-6.155 -6.16375,-7.075 -8.2,-7.075 l -31.97375,-0.002 0,-12.80625 -5.875,0 0,52.0125 2.9425,-0.004 c 0,0 25.835,-0.0362 34.90625,-0.0362 2.03625,0 5.80625,-0.9175 8.2,-7.0725 1.30375,-3.35125 2.02,-7.7925 2.02,-12.50875 0,-4.715 -0.71625,-9.1575 -2.02,-12.5075"
|
||||
inkscape:connector-curvature="0" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
53
generators/brmlab2.svg
Executable file
53
generators/brmlab2.svg
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xml:space="preserve"
|
||||
height="78.96875"
|
||||
width="78.96875"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="brmlab2.svg"
|
||||
inkscape:export-filename="/home/prusnak/work/scm/laserdisplay/svglaser/templates/template4.svg.png"
|
||||
inkscape:export-xdpi="200"
|
||||
inkscape:export-ydpi="200"><defs
|
||||
id="defs2994" /><metadata
|
||||
id="metadata78"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="689"
|
||||
id="namedview76"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="25.043829"
|
||||
inkscape:cy="5.6960585"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-global="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
id="path3237"
|
||||
style="fill:none;stroke:#000000;stroke-width:1"
|
||||
d="m 20.26276,45.39193 c -1.816875,0 -3.293437,-1.4775 -3.293437,-3.29344 0,-1.81593 1.476562,-3.29437 3.293437,-3.29437 1.816875,0 3.294375,1.47844 3.294375,3.29437 0,1.81594 -1.4775,3.29344 -3.294375,3.29344 M 39.480011,0.50605 C 17.985519,0.50605 0.5,17.99425 0.5,39.48874 c 0,10.41205 4.0546519,20.20071 11.416975,27.56304 7.363668,7.36232 17.15099,11.41697 27.563036,11.41697 21.494491,0 38.982697,-17.48686 38.982697,-38.98001 C 78.461408,17.99291 60.974502,0.50605 39.480011,0.50605 m -0.09362,68.75171 c -5.945327,0 -11.681286,-1.74473 -16.588197,-5.04528 l -0.998709,-0.67022 0.765276,-0.92531 c 1.473999,-1.78685 1.350062,-4.36785 -0.289986,-6.0079 -0.844692,-0.84469 -1.96854,-1.31035 -3.163381,-1.31035 -1.037214,0 -2.046752,0.36218 -2.843313,1.01916 l -0.926513,0.76407 -0.670218,-0.9963 C 6.757481,44.32012 8.3000651,28.49238 18.341303,18.45235 c 4.199391,-4.2018 9.490142,-7.02345 15.299501,-8.16174 l 1.179198,-0.22982 0.115514,1.19484 c 0.220197,2.30425 2.13459,4.04176 4.452076,4.04176 2.317487,0 4.23188,-1.73751 4.45328,-4.04176 l 0.115513,-1.19484 1.177996,0.22982 c 5.806952,1.13829 11.098906,3.95994 15.299501,8.15933 10.040034,10.04124 11.583822,25.87018 3.668751,37.63569 l -0.670218,0.9963 -0.92531,-0.76527 c -0.798967,-0.65698 -1.807302,-1.01796 -2.845719,-1.01796 -1.194841,0 -2.317486,0.46446 -3.163381,1.30915 -1.638845,1.64005 -1.762781,4.22225 -0.289986,6.0091 l 0.764072,0.92531 -0.996302,0.67022 c -4.90691,3.30055 -10.644073,5.04528 -16.5894,5.04528 m -7.130784,-26.72605 14.281498,0 0,-6.00112 -14.281498,0 0,6.00112 z M 24.122448,30.11568 c -1.816875,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.4775,-3.29437 3.294375,-3.29437 1.815937,0 3.293437,1.47844 3.293437,3.29437 0,1.81594 -1.4775,3.29344 -3.293437,3.29344 m 34.387656,15.27625 c -1.815937,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.478438,-3.29437 3.294375,-3.29437 1.816875,0 3.294375,1.47844 3.294375,3.29437 0,1.81594 -1.4775,3.29344 -3.294375,3.29344 m -26.905937,15.1875 c -1.815938,0 -3.292501,-1.4775 -3.292501,-3.29344 0,-1.81593 1.476563,-3.29437 3.292501,-3.29437 1.816875,0 3.294374,1.47844 3.294374,3.29437 0,1.81594 -1.477499,3.29344 -3.294374,3.29344 M 54.647291,30.11568 c -1.816874,0 -3.294374,-1.4775 -3.294374,-3.29344 0,-1.81593 1.4775,-3.29437 3.294374,-3.29437 1.815938,0 3.292501,1.47844 3.292501,3.29437 0,1.81594 -1.476563,3.29344 -3.292501,3.29344 m -7.474843,30.46375 c -1.816875,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.4775,-3.29437 3.294375,-3.29437 1.815937,0 3.293437,1.47844 3.293437,3.29437 0,1.81594 -1.4775,3.29344 -3.293437,3.29344 m -7.775,-30.46375 c -1.816875,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.4775,-3.29437 3.294375,-3.29437 1.815937,0 3.293437,1.47844 3.293437,3.29437 0,1.81594 -1.4775,3.29344 -3.293437,3.29344"
|
||||
inkscape:connector-curvature="0" /></svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
85
generators/dummy.py
Executable file
85
generators/dummy.py
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
This is the most basic generator you can imagine: straight up static!
|
||||
v0.1.0
|
||||
|
||||
Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
name="generator::dummy"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="dummy generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
color = 16777215
|
||||
square = [[100.0, 100.0, color], [100.0, 500.0, color], [500.0, 500.0, color], [500.0, 100.0, color], [100.0, 100.0, color]]
|
||||
line =[]
|
||||
for i in range(00,800,int(800/120)):
|
||||
line.append([i, 400, color])
|
||||
square = [[100.0, 100.0, color], [100.0, 500.0, color], [500.0, 500.0, color], [500.0, 100.0, color], [100.0, 100.0, color]]
|
||||
mire = [
|
||||
[600,600,0],
|
||||
[600,600,color],
|
||||
[700,600,color],
|
||||
[700,700,color],
|
||||
[600,700,color],
|
||||
[600,600,color],
|
||||
[100,100,0],
|
||||
[100,100,color],
|
||||
[200,100,color],
|
||||
[200,200,color],
|
||||
[100,200,color],
|
||||
[100,100,color],
|
||||
[0,0,0],
|
||||
[0,0,color],
|
||||
[800,0,color],
|
||||
[800,800,color],
|
||||
[0,800,color],
|
||||
[0,0,color],
|
||||
[350,400,0],
|
||||
[350,400,color],
|
||||
[450,400,color],
|
||||
[400,350,0],
|
||||
[400,350,color],
|
||||
[400,450,color],
|
||||
]
|
||||
|
||||
shape = mire
|
||||
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
182
generators/example.py
Executable file
182
generators/example.py
Executable file
|
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
example, based on custom
|
||||
v0.1.0
|
||||
|
||||
A copy of square.py you can modify to code your plugin.
|
||||
custom1 has necessary hooks in LJ.conf, webui and so on.
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by Sam Neurohack
|
||||
|
||||
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
# import from shell
|
||||
sys.path.append(ljpath +'/../../libs/')
|
||||
|
||||
#import from LJ
|
||||
sys.path.append(ljpath +'/libs/')
|
||||
print(ljpath+'/../libs/')
|
||||
|
||||
import lj23layers as lj
|
||||
|
||||
sys.path.append('../libs')
|
||||
import math
|
||||
import time
|
||||
import argparse
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Arguments parsing if needed...")
|
||||
argsparser = argparse.ArgumentParser(description="Custom1 example for LJ")
|
||||
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",default=0,type=int)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
# Useful variables init.
|
||||
white = lj.rgb2int(255,255,255)
|
||||
red = lj.rgb2int(255,0,0)
|
||||
blue = lj.rgb2int(0,0,255)
|
||||
green = lj.rgb2int(0,255,0)
|
||||
|
||||
width = 800
|
||||
height = 600
|
||||
centerX = width / 2
|
||||
centerY = height / 2
|
||||
|
||||
# 3D to 2D projection parameters
|
||||
fov = 256
|
||||
viewer_distance = 2.2
|
||||
|
||||
# Anaglyph computation parameters for right and left eyes.
|
||||
# algorythm come from anaglyph geo maps
|
||||
eye_spacing = 100
|
||||
nadir = 0.5
|
||||
observer_altitude = 30000
|
||||
map_layerane_altitude = 0.0
|
||||
|
||||
# square coordinates : vertices that compose each of the square.
|
||||
vertices = [
|
||||
(- 1.0, 1.0,- 1.0),
|
||||
( 1.0, 1.0,- 1.0),
|
||||
( 1.0,- 1.0,- 1.0),
|
||||
(- 1.0,- 1.0,- 1.0)
|
||||
]
|
||||
|
||||
face = [0,1,2,3]
|
||||
|
||||
#
|
||||
# LJ inits
|
||||
#
|
||||
|
||||
layer = 0
|
||||
|
||||
# Define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed
|
||||
Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, layer , True)
|
||||
Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, layer , True)
|
||||
|
||||
# 'Destination' for given layer : name, number, active, layer , scene, laser
|
||||
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
|
||||
|
||||
|
||||
#
|
||||
# Anaglyph computation : different X coordinate for each eye
|
||||
#
|
||||
|
||||
def LeftShift(elevation):
|
||||
|
||||
diff = elevation - map_layerane_altitude
|
||||
return nadir * eye_spacing * diff / (observer_altitude - elevation)
|
||||
|
||||
def RightShift(elevation):
|
||||
|
||||
diff = map_layerane_altitude - elevation
|
||||
return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation)
|
||||
|
||||
|
||||
def Proj(x,y,z,angleX,angleY,angleZ):
|
||||
|
||||
rad = angleX * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
y2 = y
|
||||
y = y2 * cosa - z * sina
|
||||
z = y2 * sina + z * cosa
|
||||
|
||||
rad = angleY * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
z2 = z
|
||||
z = z2 * cosa - x * sina
|
||||
x = z2 * sina + x * cosa
|
||||
|
||||
rad = angleZ * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
x2 = x
|
||||
x = x2 * cosa - y * sina
|
||||
y = x2 * sina + y * cosa
|
||||
|
||||
|
||||
""" Transforms this 3D point to 2D using a perspective projection. """
|
||||
factor = fov / (viewer_distance + z)
|
||||
x = x * factor + centerX
|
||||
y = - y * factor + centerY
|
||||
return (x,y)
|
||||
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
|
||||
def Run():
|
||||
Left = []
|
||||
Right = []
|
||||
counter =0
|
||||
try:
|
||||
while True:
|
||||
Left = []
|
||||
Right = []
|
||||
x = vertices[0][0]
|
||||
y = vertices[0][1]
|
||||
z = vertices[0][2]
|
||||
|
||||
# lj tracers will "move" the laser to this first point in black, then move to the next with second point color.
|
||||
# for more accuracy in dac emulator, repeat this first point.
|
||||
|
||||
# generate all points in square.
|
||||
for point in face:
|
||||
x = vertices[point][0]
|
||||
y = vertices[point][1]
|
||||
z = vertices[point][2]
|
||||
left.append(proj(x+leftshift(z*25),y,z,0,counter,0))
|
||||
right.append(proj(x+rightshift(z*25),y,z,0,counter,0))
|
||||
|
||||
|
||||
lj.polylineonecolor(left, c = leftsquare.color , layer = leftsquare.layer, closed = leftsquare.closed)
|
||||
lj.polylineonecolor(right, c = rightsquare.color , layer = rightsquare.layer, closed = rightsquare.closed)
|
||||
lj.drawdests()
|
||||
time.sleep(0.1)
|
||||
counter += 1
|
||||
if counter > 360:
|
||||
counter = 0
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
# Gently stop on CTRL C
|
||||
finally:
|
||||
lj.ClosePlugin()
|
||||
|
||||
|
||||
Run()
|
||||
406
generators/fromGML.py
Normal file
406
generators/fromGML.py
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromGML
|
||||
v0.1.0
|
||||
|
||||
Display a GML file
|
||||
|
||||
See GML specs at the end.
|
||||
Support the gml spec="1.0 (minimum)"
|
||||
and header/client/name
|
||||
and maybe one day drawing/brush/color
|
||||
|
||||
LICENCE : CC
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
Heavy use of : https://github.com/kgn/pygml
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import struct
|
||||
import argparse
|
||||
import sys
|
||||
import xml.etree.ElementTree as etree
|
||||
#import urllib
|
||||
from datetime import datetime
|
||||
import math, random
|
||||
import ast
|
||||
|
||||
name="generator::fromgml"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="GML file frame 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")
|
||||
argsparser.add_argument("-g","--gml",help=".gml file",default="147.gml",type=str)
|
||||
argsparser.add_argument("-t","--total",help="Total time",default=32,type=int)
|
||||
argsparser.add_argument("-m","--mode",help="once or anim mode",default="anim",type=str)
|
||||
argsparser.add_argument("-s","--skip",help="% of points to skip",default="0.4",type=float)
|
||||
argsparser.add_argument("-r","--rot",help="(angleX, angleY, angleZ) in degree",default="(0,0,270)",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
mode = args.mode
|
||||
optimal_looptime = 1 / fps
|
||||
angles = ast.literal_eval(args.rot)
|
||||
debug(name+" optimal frame time "+str(optimal_looptime))
|
||||
|
||||
|
||||
TOTAL_TIME=float(args.total)
|
||||
TIME_STRETCH = 1
|
||||
ZOOM=1.0
|
||||
DELTA = 7
|
||||
width = 500
|
||||
height = 500
|
||||
centerX = width / 2
|
||||
centerY = height / 2
|
||||
# 3D to 2D projection parameters
|
||||
fov = 200
|
||||
viewer_distance = 2.2
|
||||
|
||||
skip = args.skip
|
||||
#skip is the percentage of points that we ignore in order to render
|
||||
# faster in the laser display. Unfortunately we are not able to render too
|
||||
# complex content in our display without resulting in a lot of blinking.
|
||||
|
||||
# return a list with all points
|
||||
def readGML(filename):
|
||||
|
||||
outputData = []
|
||||
tree = etree.parse(filename)
|
||||
root = tree.getroot()
|
||||
'''
|
||||
if (root.tag.lower() != "gml"):
|
||||
print("Not a GML file.")
|
||||
return
|
||||
'''
|
||||
#~
|
||||
tag = root.find("tag")
|
||||
header = tag.find("header")
|
||||
if header != None:
|
||||
client = header.find("client")
|
||||
if client != None:
|
||||
debug("Graffiti name :", client.find("name").text)
|
||||
drawing = tag.find("drawing")
|
||||
environment = header.find("environment")
|
||||
if not environment:
|
||||
environment = tag.find("environment")
|
||||
#screenBounds = environment.find("screenBounds")
|
||||
#globalScale = (1.0,1.0,1.0)
|
||||
#dim = (float(screenBounds.find("x").text) * globalScale[0], float(screenBounds.find("y").text) * globalScale[1], float(screenBounds.find("z").text) * globalScale[2])
|
||||
#dim = (40.0,40.0,40.0)
|
||||
#~
|
||||
strokes = drawing.findall("stroke")
|
||||
for stroke in strokes:
|
||||
pointsEl = stroke.findall("pt")
|
||||
for pointEl in pointsEl:
|
||||
|
||||
x = float(pointEl.find("x").text) - 0.5
|
||||
y = float(pointEl.find("y").text) - 0.5
|
||||
z = float(pointEl.find("z").text) - 0.5
|
||||
transpoint = Rot(x,y,z,angles[0],angles[1],angles[2])
|
||||
x = (transpoint[0]*ZOOM*width/2) + (width/2)
|
||||
y = (transpoint[1]*ZOOM*height/2) + (height/2)
|
||||
z = transpoint[2]
|
||||
# WIDTH/2 + ZOOM*point[0]*WIDTH/2, HEIGHT/2 + ZOOM*point[1]*HEIGHT/2
|
||||
time = float(pointEl.find("time").text)
|
||||
outputData.append([x,y,z,time])
|
||||
#print(outputData)
|
||||
return outputData
|
||||
|
||||
def Rot(x, y, z, angleX, angleY, angleZ):
|
||||
|
||||
rad = angleX * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
y2 = y
|
||||
y = y2 * cosa - z * sina
|
||||
z = y2 * sina + z * cosa
|
||||
|
||||
rad = angleY * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
z2 = z
|
||||
z = z2 * cosa - x * sina
|
||||
x = z2 * sina + x * cosa
|
||||
|
||||
rad = angleZ * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
x2 = x
|
||||
x = x2 * cosa - y * sina
|
||||
y = x2 * sina + y * cosa
|
||||
|
||||
return (x,y,z)
|
||||
|
||||
|
||||
#[x,y,z,time]
|
||||
def iterPoints():
|
||||
|
||||
for point in gml:
|
||||
yield point
|
||||
|
||||
|
||||
# Play once during total time arg
|
||||
def Once():
|
||||
|
||||
debug(name,"play once mode")
|
||||
shape = []
|
||||
for point in gml:
|
||||
shape.append([point[0],point[1], 65535])
|
||||
debug(name + str(shape))
|
||||
|
||||
t0=datetime.now()
|
||||
deltat=0
|
||||
|
||||
while deltat<TOTAL_TIME:
|
||||
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
looptime = time.time() - start
|
||||
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
delta = datetime.now() - t0
|
||||
deltat = delta.seconds + delta.microseconds/1000000.0
|
||||
deltat = float(deltat)/TIME_STRETCH
|
||||
|
||||
|
||||
# Anim
|
||||
def Anim():
|
||||
|
||||
debug(name+" anim mode")
|
||||
t0=datetime.now()
|
||||
deltat = 0
|
||||
|
||||
while deltat<TOTAL_TIME:
|
||||
|
||||
delta = datetime.now() - t0
|
||||
deltat = delta.seconds + delta.microseconds/1000000.0
|
||||
deltat = float(deltat)/TIME_STRETCH
|
||||
|
||||
if deltat > TOTAL_TIME:
|
||||
t0=datetime.now()
|
||||
|
||||
first=True
|
||||
shape = []
|
||||
for point in iterPoints():
|
||||
if point[3] <= deltat and deltat <= point[3]+DELTA and random.random()<(1-skip):
|
||||
if first:
|
||||
first=False
|
||||
else:
|
||||
#LD.draw_point(WIDTH/2 + ZOOM*point.x*WIDTH/2, HEIGHT/2 + ZOOM*point.y*HEIGHT/2)
|
||||
shape.append([point[0], point[1], 65535])
|
||||
print(shape, flush=True);
|
||||
|
||||
|
||||
debug(name + " Reading : "+args.gml+" in "+mode+" mode.")
|
||||
gml = readGML(args.gml)
|
||||
|
||||
debug(name + " total points : "+ str(len(gml)))
|
||||
|
||||
if mode =="once":
|
||||
Once()
|
||||
else:
|
||||
Anim()
|
||||
|
||||
debug(name + " ends.")
|
||||
exit()
|
||||
'''
|
||||
|
||||
<gml spec="1.0 (minimum)">
|
||||
|
||||
<tag>
|
||||
<drawing>
|
||||
<stroke>
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
</pt>
|
||||
</stroke>
|
||||
</drawing>
|
||||
</tag>
|
||||
|
||||
</gml>
|
||||
|
||||
|
||||
|
||||
<gml spec="1.0">
|
||||
|
||||
<tag>
|
||||
|
||||
<header>
|
||||
|
||||
<client> <!-- how, who, what and where -->
|
||||
<name>Laser Tag</name> <!-- application name -->
|
||||
<version>2.0</version> <!-- application version -->
|
||||
<username>MyUserName</username> <!-- user name on 000000book.com, optional -->
|
||||
<permalink>http://000000book.com/data/156/</permalink> <!-- URL to .gml data on 000000book.com, optional -->
|
||||
<keywords>katsu,paris,2010</keywords> <!-- comma-separated -->
|
||||
<uniquekey>28sks922ks992</uniquekey> <!-- iPhone uuid, MAC address, etc -->
|
||||
<ip>192.168.1.1</ip>
|
||||
<time>1928372722</time> <!-- unixtime -->
|
||||
<location>
|
||||
<lon>-39.392922</lon>
|
||||
<lat>53.29292</lat>
|
||||
</location>
|
||||
</client>
|
||||
|
||||
<!-- This is all stuff that relates to the orientation and dimensions of the client -->
|
||||
<!-- So that we know how to re-map the 0.0-1.0 coordinates that come in for each point -->
|
||||
<!-- Also for figuring out the down vector for devices with accelerometers and how that effects drips -->
|
||||
<!-- All numbers should be between 0.0 - 1.0 -->
|
||||
<environment>
|
||||
<offset>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z>
|
||||
</offset>
|
||||
<rotation>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z>
|
||||
</rotation>
|
||||
<up>
|
||||
<x>0.0</x> <!-- commonly up for iphone apps -->
|
||||
<y>-1.0</y> <!-- most common -->
|
||||
<z>0.0</z>
|
||||
</up>
|
||||
<screenbounds> <!-- use this as your multipler to get 0.0 to 1.0 back to right size - pts should never go off 0.0 to 1.0 -->
|
||||
<x>1024</x>
|
||||
<y>768</y>
|
||||
<z>0</z>
|
||||
</screenbounds>
|
||||
<origin>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<z>0</z>
|
||||
</origin>
|
||||
<realscale> <!-- how these units relate to real world units - good for laser tag -->
|
||||
<x>1000</x>
|
||||
<y>600</y>
|
||||
<z>0</z>
|
||||
<unit>cm</unit>
|
||||
</realscale>
|
||||
<audio>youraudio.mp3</audio> <!-- path to audio file -->
|
||||
<background>yourimage.jpg</background> <!-- path to image file -->
|
||||
</environment>
|
||||
|
||||
</header>
|
||||
|
||||
<drawing>
|
||||
<!-- for all stroke and movement stuff it helps to have everything inside the stroke tag -->
|
||||
<!-- this way it is easy to get a sense of order to events -->
|
||||
|
||||
<stroke isdrawing="false"> <!-- for non drawing mouse movements -->
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z> <!--this is optional -->
|
||||
<t>0.013</t> <!-- time is optional too -->
|
||||
<!-- NOTE: older versions of GML use <time> instead of <t> -->
|
||||
</pt>
|
||||
</stroke>
|
||||
|
||||
<stroke> <!-- by default stroke drawing is true -->
|
||||
|
||||
<!-- each stroke could be drawn with a different brush -->
|
||||
<!-- if no brush tag is found for a stroke then it inherits the previous settings -->
|
||||
<brush>
|
||||
<mode>0</mode> <!-- same as uniqueStyleID but an internal reference -->
|
||||
<uniquestyleid>LaserTagArrowLetters</uniquestyleid> <!-- unique blackbook string for your style -->
|
||||
<!-- see note about spec at the bottom - like unique style but with extra info -->
|
||||
<spec>http://aurltodescribethebrushspec.com/someSpec.xml</spec>
|
||||
<width>10</width>
|
||||
<speedtowidthratio>1.5</speedtowidthratio> <!-- put 0 for fixed width -->
|
||||
<dripamnt>1.0</dripamnt>
|
||||
<dripspeed>1.0</dripspeed>
|
||||
<layerabsolute>0</layerabsolute> <!--Think photoshop layers-->
|
||||
<color>
|
||||
<r>255</r>
|
||||
<g>255</g>
|
||||
<b>255</b>
|
||||
<a>255</a> <!-- optional -->
|
||||
</color>
|
||||
<dripvecrelativetoup> <!-- what angle do our drips go in relation to our up vector -->
|
||||
<x>0</x>
|
||||
<y>1</y>
|
||||
<z>0</z>
|
||||
</dripvecrelativetoup>
|
||||
</brush>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z> <!--this is optional -->
|
||||
<t>0.013</t> <!-- time is optional too -->
|
||||
</pt>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z> <!--this is optional -->
|
||||
<t>0.023</t> <!-- time is optional too -->
|
||||
</pt>
|
||||
|
||||
|
||||
</stroke>
|
||||
|
||||
<!-- this stroke inherits the previous stroke properties -->
|
||||
<!-- but changes color and draws on the layer below -->
|
||||
<stroke>
|
||||
<info> <!-- optional info - more stuff soon-->
|
||||
<curved>true</curved>
|
||||
</info>
|
||||
<brush>
|
||||
<color>
|
||||
<r>255</r>
|
||||
<g>255</g>
|
||||
<b>0</b>
|
||||
</color>
|
||||
<layerrelative> <!-- this means one layer bellow the previous layer -->
|
||||
-1
|
||||
</layerrelative>
|
||||
</brush>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
</pt>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
</pt>
|
||||
|
||||
</stroke>
|
||||
|
||||
<stroke>
|
||||
<pt>
|
||||
<pres>0.5</pres> <!-- Optional. Preasure range from 0 to 1 -->
|
||||
<rot>0.5</rot> <!-- Optional. Rotation range from 0 to 1 for 0 to 2*PI -->
|
||||
<dir> <!-- Optional Direction -->
|
||||
<x></x> <!-- range from 0 to 1 -->
|
||||
<y></y> <!-- range from 0 to 1 -->
|
||||
<z></z> <!-- Optional inside direction. Range from 0 to 1 -->
|
||||
</dir>
|
||||
</pt>
|
||||
</stroke>
|
||||
</drawing>
|
||||
|
||||
</tag>
|
||||
|
||||
</gml>
|
||||
'''
|
||||
126
generators/fromOSC.py
Normal file
126
generators/fromOSC.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
Forward /pl pointlist to cli
|
||||
|
||||
input OSC in END points format : (x,y,color)
|
||||
output CLI in CLI points format : [x,y,color]
|
||||
|
||||
/pl "[(150.0, 230.0, 255), (170.0, 170.0, 255), (230.0, 170.0, 255), (210.0, 230.0, 255), (150.0, 230.0, 255)]"
|
||||
|
||||
v0.1.0
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by Cocoa, Sam Neurohack
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import sys
|
||||
from time import sleep
|
||||
import argparse
|
||||
import ast
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="fromOSC generator")
|
||||
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
|
||||
argsparser.add_argument("-p","--port",help="OSC port to bind to (9002 by default)",default=9002,type=str)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = int(args.port)
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
oscserver = OSCServer( (ip, port) )
|
||||
oscserver.timeout = 0
|
||||
run = True
|
||||
|
||||
# this method of reporting timeouts only works by convention
|
||||
# that before calling handle_request() field .timed_out is
|
||||
# set to False
|
||||
def handle_timeout(self):
|
||||
self.timed_out = True
|
||||
|
||||
# funny python's way to add a method to an instance of a class
|
||||
import types
|
||||
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSC_frame():
|
||||
# clear timed_out flag
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(oscpath, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(oscpath.split("/"))
|
||||
debug("fromOSC Default OSC Handler got oscpath", oscpath, "from" + str(source[0]), ":", args)
|
||||
#print("OSC address", path)
|
||||
#print("find.. /bhoreal ?", path.find('/bhoreal'))
|
||||
|
||||
if oscpath == "/pl" and len(args)==1:
|
||||
|
||||
debug("correct OSC type :'/pl")
|
||||
|
||||
if validate(args[0]) == True:
|
||||
|
||||
debug("new pl : ", args[0])
|
||||
line = args[0].replace("(",'[')
|
||||
line = line.replace(")",']')
|
||||
line = "[{}]".format(line)
|
||||
print(line, flush=True);
|
||||
|
||||
else:
|
||||
debug("Bad pointlist -> msg trapped.")
|
||||
|
||||
else:
|
||||
debug("BAD OSC Message : " + oscpath +" " +args[0])
|
||||
|
||||
|
||||
oscserver.addMsgHandler( "default", OSChandler )
|
||||
|
||||
|
||||
def validate(pointlist):
|
||||
|
||||
state = True
|
||||
|
||||
if len(pointlist)<9:
|
||||
debug("Not enough characters :", pointlist)
|
||||
state = False
|
||||
|
||||
if pointlist.find("(") == -1:
|
||||
debug("Bad format : use () not [] for points", pointlist)
|
||||
state = False
|
||||
|
||||
try:
|
||||
pl = bytes(pointlist, 'ascii')
|
||||
check = ast.literal_eval(pl.decode('ascii'))
|
||||
|
||||
except:
|
||||
debug("BAD POINTLIST :", pointlist)
|
||||
state = False
|
||||
|
||||
return state
|
||||
|
||||
|
||||
# simulate a "game engine"
|
||||
while run:
|
||||
# do the game stuff:
|
||||
sleep(0.01)
|
||||
# call user script
|
||||
OSC_frame()
|
||||
|
||||
oscserver.close()
|
||||
|
||||
72
generators/fromRedis.py
Executable file
72
generators/fromRedis.py
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
This generator reads a frame from redis
|
||||
v0.1.0
|
||||
|
||||
Use it to create feedback loops by writing to the same frame
|
||||
or to copy the frame from someone else
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import ast
|
||||
import argparse
|
||||
import json
|
||||
import redis
|
||||
import sys
|
||||
import time
|
||||
name="generator::fromRedis"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Dummy generator")
|
||||
argsparser.add_argument("-k","--key",required=True,help="Redis key to look after",default=30,type=str)
|
||||
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("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps = args.fps
|
||||
verbose = args.verbose
|
||||
key = args.key
|
||||
ip = args.ip
|
||||
port = args.port
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
r = redis.Redis(
|
||||
host=ip,
|
||||
port=port)
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
# Read from Redis
|
||||
line = r.get(key)
|
||||
# Decode as list of tuples
|
||||
pointsList = ast.literal_eval(line.decode('ascii'))
|
||||
# convert to list of lists
|
||||
pointsList = [list(elem) for elem in pointsList]
|
||||
# Convert to JSON string
|
||||
line = json.dumps( pointsList )
|
||||
debug(name,"Key:{} line:{}".format(key,line))
|
||||
print(line, flush=True);
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
84
generators/fromUDP.py
Normal file
84
generators/fromUDP.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromUDP
|
||||
|
||||
Udp server to cli
|
||||
v0.1b
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import traceback, time
|
||||
import argparse
|
||||
import socket
|
||||
import _thread
|
||||
import sys
|
||||
|
||||
name="generator::fromUDP"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="fromUDP v0.1b help mode")
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
|
||||
argsparser.add_argument("-p","--port",help="UDP port to bind to (9000 by default)",default=9000,type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = int(args.port)
|
||||
verbose = args.verbose
|
||||
|
||||
|
||||
|
||||
def udp_thread():
|
||||
|
||||
while True:
|
||||
|
||||
payload, client_address = sock.recvfrom(1024)
|
||||
udpath = payload.decode('utf_8')
|
||||
debug(udpath[0:])
|
||||
print(udpath[0:], flush=True);
|
||||
|
||||
'''
|
||||
# Reply to client
|
||||
bytesToSend = str.encode("ACK :"+str(payload))
|
||||
serverAddressPort = (client_address, port)
|
||||
bufferSize = 1024
|
||||
#sock.sendto(bytesToSend, serverAddressPort)
|
||||
sock.sendto(bytesToSend, client_address)
|
||||
'''
|
||||
|
||||
def StartUDP(serverIP, UDPORT):
|
||||
global sock
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
server = ( serverIP,UDPORT)
|
||||
sock.bind(server)
|
||||
_thread.start_new_thread(udp_thread, ())
|
||||
|
||||
|
||||
StartUDP(ip, port)
|
||||
|
||||
|
||||
# Do something else
|
||||
try:
|
||||
|
||||
while True:
|
||||
time.sleep(0.005)
|
||||
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
319
generators/fromilda.py
Normal file
319
generators/fromilda.py
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromild
|
||||
v0.1.0
|
||||
|
||||
Read/display once an .ild animation file and quit ??
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
Heavy u-se of :
|
||||
|
||||
ILDA.py
|
||||
|
||||
Python module for dealing with the ILDA Image Data Transfer Format,
|
||||
an interchange format for laser image frames.
|
||||
|
||||
Copyright (c) 2008 Micah Dowty
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import struct
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
name="generator::fromild"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description=".ild file frame 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")
|
||||
argsparser.add_argument("-i","--ild",help=".ild file",default="book2.ild",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
# Format codes
|
||||
FORMAT_3D = 0
|
||||
FORMAT_2D = 1
|
||||
FORMAT_COLOR_TABLE = 2
|
||||
|
||||
# Mapping from FORMAT_* codes to struct format strings
|
||||
formatTable = (
|
||||
'>hhhH',
|
||||
'>hhH',
|
||||
'>BBB',
|
||||
)
|
||||
|
||||
# Header values
|
||||
HEADER_MAGIC = b"ILDA\0\0\0"
|
||||
HEADER_RESERVED = 0
|
||||
HEADER_FORMAT = ">7sB16sHHHBB"
|
||||
HEADER_LEN = struct.calcsize(HEADER_FORMAT)
|
||||
|
||||
# 64 default colors table : use rgb2int(colors64[ildacolor])
|
||||
colors64 = [[255, 0, 0], [255, 17, 0], [255, 34, 0], [255, 51, 0], [255, 68, 0], [255, 85, 0], [255, 102, 0], [255, 119, 0], [255, 136, 0], [255, 153, 0], [255, 170, 0], [255, 187, 0], [255, 204, 0], [255, 221, 0], [255, 238, 0], [255, 255, 0], [255, 255, 0], [238, 255, 0], [204, 255, 0], [170, 255, 0], [136, 255, 0], [102, 255, 0], [68, 255, 0], [34, 255, 0], [0, 255, 0], [0, 255, 34], [0, 255, 68], [0, 255, 102], [0, 255, 136], [0, 255, 170], [0, 255, 204], [0, 255, 238], [0, 136, 255], [0, 119, 255], [0, 102, 255], [0, 102, 255], [0, 85, 255], [0, 68, 255], [0, 68, 255], [0, 34, 255], [0, 0, 255], [34, 0, 255], [68, 0, 255], [102, 0, 255], [136, 0, 255], [170, 0, 255], [204, 0, 255], [238, 0, 255], [255, 0, 255], [255, 34, 255], [255, 68, 255], [255, 102, 255], [255, 136, 255], [255, 170, 255], [255, 204, 255], [255, 238, 255], [255, 255, 255], [255, 238, 238], [255, 204, 204], [255, 170, 170], [255, 136, 136], [255, 102, 102], [255, 68, 68], [0, 34, 34]]
|
||||
|
||||
|
||||
# 256 default colors table
|
||||
colors256 = [[0, 0, 0], [255, 255, 255], [255, 0, 0], [255, 255, 0], [0, 255, 0], [0, 255, 255], [0, 0, 255], [255, 0, 255], [255, 128, 128], [255, 140, 128], [255, 151, 128], [255, 163, 128], [255, 174, 128], [255, 186, 128], [255, 197, 128], [255, 209, 128], [255, 220, 128], [255, 232, 128], [255, 243, 128], [255, 255, 128], [243, 255, 128], [232, 255, 128], [220, 255, 128], [209, 255, 128], [197, 255, 128], [186, 255, 128], [174, 255, 128], [163, 255, 128], [151, 255, 128], [140, 255, 128], [128, 255, 128], [128, 255, 140], [128, 255, 151], [128, 255, 163], [128, 255, 174], [128, 255, 186], [128, 255, 197], [128, 255, 209], [128, 255, 220], [128, 255, 232], [128, 255, 243], [128, 255, 255], [128, 243, 255], [128, 232, 255], [128, 220, 255], [128, 209, 255], [128, 197, 255], [128, 186, 255], [128, 174, 255], [128, 163, 255], [128, 151, 255], [128, 140, 255], [128, 128, 255], [140, 128, 255], [151, 128, 255], [163, 128, 255], [174, 128, 255], [186, 128, 255], [197, 128, 255], [209, 128, 255], [220, 128, 255], [232, 128, 255], [243, 128, 255], [255, 128, 255], [255, 128, 243], [255, 128, 232], [255, 128, 220], [255, 128, 209], [255, 128, 197], [255, 128, 186], [255, 128, 174], [255, 128, 163], [255, 128, 151], [255, 128, 140], [255, 0, 0], [255, 23, 0], [255, 46, 0], [255, 70, 0], [255, 93, 0], [255, 116, 0], [255, 139, 0], [255, 162, 0], [255, 185, 0], [255, 209, 0], [255, 232, 0], [255, 255, 0], [232, 255, 0], [209, 255, 0], [185, 255, 0], [162, 255, 0], [139, 255, 0], [116, 255, 0], [93, 255, 0], [70, 255, 0], [46, 255, 0], [23, 255, 0], [0, 255, 0], [0, 255, 23], [0, 255, 46], [0, 255, 70], [0, 255, 93], [0, 255, 116], [0, 255, 139], [0, 255, 162], [0, 255, 185], [0, 255, 209], [0, 255, 232], [0, 255, 255], [0, 232, 255], [0, 209, 255], [0, 185, 255], [0, 162, 255], [0, 139, 255], [0, 116, 255], [0, 93, 255], [0, 70, 255], [0, 46, 255], [0, 23, 255], [0, 0, 255], [23, 0, 255], [46, 0, 255], [70, 0, 255], [93, 0, 255], [116, 0, 255], [139, 0, 255], [162, 0, 255], [185, 0, 255], [209, 0, 255], [232, 0, 255], [255, 0, 255], [255, 0, 232], [255, 0, 209], [255, 0, 185], [255, 0, 162], [255, 0, 139], [255, 0, 116], [255, 0, 93], [255, 0, 70], [255, 0, 46], [255, 0, 23], [128, 0, 0], [128, 12, 0], [128, 23, 0], [128, 35, 0], [128, 47, 0], [128, 58, 0], [128, 70, 0], [128, 81, 0], [128, 93, 0], [128, 105, 0], [128, 116, 0], [128, 128, 0], [116, 128, 0], [105, 128, 0], [93, 128, 0], [81, 128, 0], [70, 128, 0], [58, 128, 0], [47, 128, 0], [35, 128, 0], [23, 128, 0], [12, 128, 0], [0, 128, 0], [0, 128, 12], [0, 128, 23], [0, 128, 35], [0, 128, 47], [0, 128, 58], [0, 128, 70], [0, 128, 81], [0, 128, 93], [0, 128, 105], [0, 128, 116], [0, 128, 128], [0, 116, 128], [0, 105, 128], [0, 93, 128], [0, 81, 128], [0, 70, 128], [0, 58, 128], [0, 47, 128], [0, 35, 128], [0, 23, 128], [0, 12, 128], [0, 0, 128], [12, 0, 128], [23, 0, 128], [35, 0, 128], [47, 0, 128], [58, 0, 128], [70, 0, 128], [81, 0, 128], [93, 0, 128], [105, 0, 128], [116, 0, 128], [128, 0, 128], [128, 0, 116], [128, 0, 105], [128, 0, 93], [128, 0, 81], [128, 0, 70], [128, 0, 58], [128, 0, 47], [128, 0, 35], [128, 0, 23], [128, 0, 12], [255, 192, 192], [255, 64, 64], [192, 0, 0], [64, 0, 0], [255, 255, 192], [255, 255, 64], [192, 192, 0], [64, 64, 0], [192, 255, 192], [64, 255, 64], [0, 192, 0], [0, 64, 0], [192, 255, 255], [64, 255, 255], [0, 192, 192], [0, 64, 64], [192, 192, 255], [64, 64, 255], [0, 0, 192], [0, 0, 64], [255, 192, 255], [255, 64, 255], [192, 0, 192], [64, 0, 64], [255, 96, 96], [255, 255, 255], [245, 245, 245], [235, 235, 235], [224, 224, 224], [213, 213, 213], [203, 203, 203], [192, 192, 192], [181, 181, 181], [171, 171, 171], [160, 160, 160], [149, 149, 149], [139, 139, 139], [128, 128, 128], [117, 117, 117], [107, 107, 107], [96, 96, 96], [85, 85, 85], [75, 75, 75], [64, 64, 64], [53, 53, 53], [43, 43, 43], [32, 32, 32], [21, 21, 21], [11, 11, 11], [0, 0, 0]]
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
class Table(object):
|
||||
"""Container object for one ILDA table: either a frame (table of points)
|
||||
or a palette (table of colors).
|
||||
|
||||
The 'items' list contains the data within this table. Each item
|
||||
is a tuple, corresponding to the raw values within that row of the
|
||||
table.
|
||||
|
||||
2D frame: (x, y, status)
|
||||
3D frame: (x, y, z, status)
|
||||
Color: (r, g, b)
|
||||
|
||||
"""
|
||||
def __init__(self, format=FORMAT_2D, name="",
|
||||
length=0, number=0, total=0, scanHead=0):
|
||||
self.__dict__.update(locals())
|
||||
self.items = []
|
||||
self.itemsproducer = None
|
||||
|
||||
def __repr__(self):
|
||||
return ("<ILDA.Table format=%d name=%r "
|
||||
"length=%d number=%d total=%d scanHead=%d>" %
|
||||
(self.format, self.name, self.length, self.number,
|
||||
self.total, self.scanHead))
|
||||
|
||||
def unpackHeader(self, data):
|
||||
magic, self.format, self.name, self.length, \
|
||||
self.number, self.total, self.scanHead, \
|
||||
reserved = struct.unpack(HEADER_FORMAT, data)
|
||||
print(magic, HEADER_MAGIC)
|
||||
if magic != HEADER_MAGIC:
|
||||
raise ValueError("Bad ILDA header magic. Not an ILDA file?")
|
||||
if reserved != HEADER_RESERVED:
|
||||
raise ValueError("Reserved ILDA field is not zero.")
|
||||
|
||||
def packHeader(self):
|
||||
return struct.pack(HEADER_FORMAT, HEADER_MAGIC, self.format,
|
||||
self.name, self.length, self.number,
|
||||
self.total, self.scanHead, HEADER_RESERVED)
|
||||
|
||||
def readHeader(self, stream):
|
||||
self.unpackHeader(stream.read(HEADER_LEN))
|
||||
|
||||
def writeHeader(self, stream):
|
||||
stream.write(self.packHeader())
|
||||
|
||||
def _getItemFormat(self):
|
||||
try:
|
||||
return formatTable[self.format]
|
||||
except IndexError:
|
||||
raise ValueError("Unsupported format code")
|
||||
|
||||
def read_stream(self, stream):
|
||||
"""Read the header, then read all items in this table."""
|
||||
self.readHeader(stream)
|
||||
if self.length:
|
||||
fmt = self._getItemFormat()
|
||||
itemSize = struct.calcsize(fmt)
|
||||
self.items = [struct.unpack(fmt, stream.read(itemSize))
|
||||
for i in range(self.length)]
|
||||
self.itemsproducer = self.produce()
|
||||
|
||||
def write(self, stream):
|
||||
"""Write the header, then write all items in this table."""
|
||||
self.writeHeader(stream)
|
||||
if self.length:
|
||||
fmt = self._getItemFormat()
|
||||
itemSize = struct.calcsize(fmt)
|
||||
stream.write(''.join([struct.pack(fmt, *item)
|
||||
for item in self.items]))
|
||||
|
||||
def iterPoints(self):
|
||||
"""Iterate over Point instances for each item in this table.
|
||||
Only makes sense if this is a 2D or 3D point table.
|
||||
"""
|
||||
for item in self.items:
|
||||
p = Point()
|
||||
p.decode(item)
|
||||
yield p
|
||||
|
||||
|
||||
def produce(self):
|
||||
"""Iterate over Point instances for each item in this table.
|
||||
Only makes sense if this is a 2D or 3D point table.
|
||||
"""
|
||||
while True:
|
||||
for item in self.items:
|
||||
p = Point()
|
||||
p.decode(item)
|
||||
yield p.encode()
|
||||
#yield (p.x, p.y, p.z, p.color, p.blanking)
|
||||
|
||||
def read(self, cap):
|
||||
"""yields what dac.play_stream() needs (x, y, z, ?, ?)
|
||||
"""
|
||||
return [next(self.itemsproducer) for i in range(cap)]
|
||||
|
||||
|
||||
class Point:
|
||||
"""Abstraction for one vector point. The Table object, for
|
||||
completeness and efficiency, stores raw tuples for each
|
||||
point. This is a higher level interface that decodes the status
|
||||
bits and represents coordinates in floating point.
|
||||
"""
|
||||
def __init__(self, x=0.0, y=0.0, z=0.0, color=0, blanking=False):
|
||||
self.__dict__.update(locals())
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
return "%s, %s, %s, %s, %s" % (
|
||||
self.x, self.y, self.z, self.color, self.blanking)
|
||||
#return "<ILDA.Point (%s, %s, %s) color=%s blanking=%s>" % (
|
||||
# self.x, self.y, self.z, self.color, self.blanking)
|
||||
|
||||
def encode(self):
|
||||
status = self.color & 0xFF
|
||||
if self.blanking:
|
||||
status |= 1 << 14
|
||||
|
||||
return (
|
||||
int( min(0x7FFF, max(-0x7FFF, self.x * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.y * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.z * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.color * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.blanking * 0x7FFF)) )
|
||||
)
|
||||
|
||||
def decode(self, t):
|
||||
#print "~~ Decoding, t of len "+ str(len(t)) +" is: " + str(t)
|
||||
self.x = t[0] / 0x7FFF
|
||||
self.y = t[1] / 0x7FFF
|
||||
if len(t) > 3:
|
||||
self.z = t[2] / 0x7FFF
|
||||
# self.color = t[3] & 0xFF
|
||||
# self.blanking = (t[3] & (1 << 14)) != 0
|
||||
else:
|
||||
self.z = 0.0
|
||||
|
||||
self.color = t[-1] & 0xFF
|
||||
self.blanking = (t[-1] & (1 << 14)) != 0
|
||||
|
||||
|
||||
def read(stream):
|
||||
"""Read ILDA data from a stream until we hit the
|
||||
end-of-stream marker. Yields a sequence of Table objects.
|
||||
"""
|
||||
while True:
|
||||
t = Table()
|
||||
t.read_stream(stream)
|
||||
if not t.length:
|
||||
# End-of-stream
|
||||
break
|
||||
yield t
|
||||
|
||||
|
||||
def write(stream, tables):
|
||||
"""Write a sequence of tables in ILDA format,
|
||||
terminated by an end-of-stream marker.
|
||||
"""
|
||||
for t in tables:
|
||||
t.write(stream)
|
||||
Table().write(stream)
|
||||
|
||||
|
||||
def readFrames(stream):
|
||||
"""Read ILDA data from a stream, and ignore
|
||||
all non-frame tables. Yields only 2D or 3D
|
||||
point tables.
|
||||
"""
|
||||
for t in read(stream):
|
||||
if t.format in (FORMAT_2D, FORMAT_3D):
|
||||
yield t
|
||||
|
||||
|
||||
def readFirstFrame(stream):
|
||||
"""Read only a single frame from an ILDA stream."""
|
||||
for frame in readFrames(stream):
|
||||
return frame
|
||||
|
||||
|
||||
#
|
||||
f = open(args.ild, 'rb')
|
||||
myframe = readFirstFrame(f)
|
||||
|
||||
while myframe.number +1< myframe.total:
|
||||
|
||||
start = time.time()
|
||||
shape =[]
|
||||
|
||||
if myframe is None:
|
||||
f.close()
|
||||
break
|
||||
|
||||
debug(name,"Frame", myframe.number, "/",myframe.total, "length", myframe.length)
|
||||
|
||||
for p in myframe.iterPoints():
|
||||
p2 = str(p)
|
||||
point = p2.split(',')
|
||||
|
||||
x = float(point[0])
|
||||
y = float(point[1])
|
||||
z = float(point[2])
|
||||
color = int(point[3])
|
||||
blanking = point[4][1:]
|
||||
|
||||
if blanking == "True":
|
||||
shape.append([300+(x*300),300+(-y*300),0])
|
||||
else:
|
||||
shape.append([300+(x*300),300+(-y*300),rgb2int(colors64[color])])
|
||||
|
||||
print(shape, flush=True);
|
||||
myframe = readFirstFrame(f)
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
f.close()
|
||||
debug(name + " end of .ild animation")
|
||||
131
generators/osc2redis.py
Normal file
131
generators/osc2redis.py
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
Forward pointlist to redis key
|
||||
|
||||
END POINT Format : (x,y,color)
|
||||
|
||||
/pl/0/0 "[(150.0, 230.0, 255), (170.0, 170.0, 255), (230.0, 170.0, 255), (210.0, 230.0, 255), (150.0, 230.0, 255)]"
|
||||
|
||||
v0.1.0
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by Cocoa, Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import sys
|
||||
from time import sleep
|
||||
import argparse
|
||||
import ast
|
||||
import redis
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="osc2redis generator")
|
||||
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
|
||||
argsparser.add_argument("-p","--port",help="OSC port to bind to (9002 by default)",default=9002,type=str)
|
||||
|
||||
argsparser.add_argument("-r","--rip",help="Redis server IP (127.0.0.1 by default)",default="127.0.0.1",type=str)
|
||||
argsparser.add_argument("-o","--rout",help="Redis port (6379 by default)",default=6379,type=str)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = int(args.port)
|
||||
rip = args.rip
|
||||
rport = int(args.rout)
|
||||
|
||||
|
||||
r = redis.StrictRedis(host=rip, port=rport, db=0)
|
||||
|
||||
|
||||
def debug(msg):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(msg)
|
||||
|
||||
|
||||
oscserver = OSCServer( (ip, port) )
|
||||
oscserver.timeout = 0
|
||||
run = True
|
||||
|
||||
# this method of reporting timeouts only works by convention
|
||||
# that before calling handle_request() field .timed_out is
|
||||
# set to False
|
||||
def handle_timeout(self):
|
||||
self.timed_out = True
|
||||
|
||||
# funny python's way to add a method to an instance of a class
|
||||
import types
|
||||
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||
|
||||
|
||||
def validate(pointlist):
|
||||
|
||||
state = True
|
||||
|
||||
if len(pointlist)<9:
|
||||
state = False
|
||||
|
||||
try:
|
||||
pl = bytes(pointlist, 'ascii')
|
||||
check = ast.literal_eval(pl.decode('ascii'))
|
||||
|
||||
except:
|
||||
state = False
|
||||
|
||||
return state
|
||||
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSC_frame():
|
||||
# clear timed_out flag
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(oscpath, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(oscpath.split("/"))
|
||||
print("fromOSC Default OSC Handler got oscpath :", oscpath, "from :" + str(source[0]), "args :", args)
|
||||
print(oscpath.find("/pl/"), len(oscpath))
|
||||
|
||||
if oscpath.find("/pl/") ==0 and len(args)==1:
|
||||
|
||||
print("correct OSC type :'/pl/")
|
||||
|
||||
if validate(args[0]) == True and len(oscpath) == 7:
|
||||
print("new pl for key ", oscpath, ":", args[0])
|
||||
|
||||
if r.set(oscpath,args[0])==True:
|
||||
debug("exports::redis set("+str(oscpath)+") to "+args[0])
|
||||
|
||||
else:
|
||||
print("Bad pointlist -> msg trapped.")
|
||||
|
||||
|
||||
else:
|
||||
print("BAD OSC Message :", oscpath)
|
||||
|
||||
oscserver.addMsgHandler( "default", OSChandler )
|
||||
|
||||
|
||||
|
||||
|
||||
# simulate a "game engine"
|
||||
while run:
|
||||
# do the game stuff:
|
||||
sleep(0.01)
|
||||
# call user script
|
||||
OSC_frame()
|
||||
|
||||
oscserver.close()
|
||||
|
||||
174
generators/redilysis_lines.py
Executable file
174
generators/redilysis_lines.py
Executable file
|
|
@ -0,0 +1,174 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
redilysis_lines
|
||||
v0.1.0
|
||||
|
||||
Add a line on every frame and scroll
|
||||
|
||||
see https://git.interhacker.space/teamlaser/redilysis for more informations
|
||||
about the redilysis project
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import ast
|
||||
import os
|
||||
import math
|
||||
import random
|
||||
import redis
|
||||
import sys
|
||||
import time
|
||||
name = "generator::redilysis_lines"
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
def msNow():
|
||||
return time.time()
|
||||
|
||||
CHAOS = 1
|
||||
REDIS_FREQ = 33
|
||||
|
||||
# General Args
|
||||
argsparser = argparse.ArgumentParser(description="Redilysis filter")
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")
|
||||
# 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("-F","--redis-freq",help="Query Redis every x (in milliseconds). Default:{}".format(REDIS_FREQ),default=REDIS_FREQ,type=int)
|
||||
# General args
|
||||
argsparser.add_argument("-n","--nlines",help="number of lines on screen",default=60,type=int)
|
||||
argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int)
|
||||
argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int)
|
||||
argsparser.add_argument("-W","--max-width",help="geometrical max width",default=800,type=int)
|
||||
argsparser.add_argument("-H","--max-height",help="geometrical max height",default=800,type=int)
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
|
||||
args = argsparser.parse_args()
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = args.port
|
||||
fps = args.fps
|
||||
centerX = args.centerX
|
||||
centerY = args.centerY
|
||||
redisFreq = args.redis_freq / 1000
|
||||
maxWidth = args.max_width
|
||||
maxHeight = args.max_height
|
||||
nlines = args.nlines
|
||||
optimal_looptime = 1 / fps
|
||||
|
||||
redisKeys = ["spectrum_120","spectrum_10"]
|
||||
debug(name,"Redis Keys:{}".format(redisKeys))
|
||||
redisData = {}
|
||||
redisLastHit = msNow() - 99999
|
||||
r = redis.Redis(
|
||||
host=ip,
|
||||
port=port)
|
||||
|
||||
white = 16777215
|
||||
lineList = []
|
||||
|
||||
scroll_speed = int(maxHeight / nlines )
|
||||
line_length = int(maxWidth / 10)
|
||||
line_pattern = []
|
||||
|
||||
def rgb2int(rgb):
|
||||
#debug(name,"::rgb2int rbg:{}".format(rgb))
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
def spectrum_10( ):
|
||||
delList = []
|
||||
spectrum = ast.literal_eval(redisData["spectrum_10"])
|
||||
debug( name, "spectrum:{}".format(spectrum))
|
||||
# scroll lines
|
||||
for i,line in enumerate(lineList):
|
||||
skip_line = False
|
||||
new_y = int(line[0][1] + scroll_speed)
|
||||
if( new_y >= maxHeight ):
|
||||
debug(name,"{} > {}".format(new_y,maxHeight))
|
||||
debug(name,"delete:{}".format(i))
|
||||
delList.append(i)
|
||||
continue
|
||||
|
||||
for j,point in enumerate(line):
|
||||
line[j][1] = new_y
|
||||
lineList[i] = line
|
||||
|
||||
for i in delList:
|
||||
del lineList[i]
|
||||
|
||||
# new line
|
||||
currentLine = []
|
||||
for i in range(0,10):
|
||||
x = int(i * line_length)
|
||||
y = 0
|
||||
# get frequency level
|
||||
level = spectrum[i]
|
||||
# get color
|
||||
comp = int(255*level)
|
||||
color = rgb2int( (comp,comp,comp))
|
||||
# new point
|
||||
currentLine.append( [x,y,color] )
|
||||
|
||||
# add line to list
|
||||
lineList.append( currentLine)
|
||||
|
||||
|
||||
def refreshRedis():
|
||||
global redisLastHit
|
||||
global redisData
|
||||
# Skip if cache is sufficent
|
||||
diff = msNow() - redisLastHit
|
||||
if diff < redisFreq :
|
||||
#debug(name, "refreshRedis not updating redis, {} < {}".format(diff, redisFreq))
|
||||
pass
|
||||
else:
|
||||
#debug(name, "refreshRedis updating redis, {} > {}".format(diff, redisFreq))
|
||||
redisLastHit = msNow()
|
||||
for key in redisKeys:
|
||||
redisData[key] = r.get(key).decode('ascii')
|
||||
#debug(name,"refreshRedis key:{} value:{}".format(key,redisData[key]))
|
||||
# Only update the TTLs
|
||||
if 'bpm' in redisKeys:
|
||||
redisData['bpm_pttl'] = r.pttl('bpm')
|
||||
#debug(name,"refreshRedis key:bpm_ttl value:{}".format(redisData["bpm_pttl"]))
|
||||
#debug(name,"redisData:{}".format(redisData))
|
||||
return True
|
||||
|
||||
def linelistToPoints( lineList ):
|
||||
pl = []
|
||||
for i,line in enumerate(lineList):
|
||||
# add a blank point
|
||||
pl.append([ line[0][0], line[0][1], 0 ])
|
||||
# append all the points of the line
|
||||
pl += line
|
||||
#debug(name,"pl:{}".format(pl))
|
||||
debug(name,"pl length:{}".format(len(pl)))
|
||||
return pl
|
||||
|
||||
try:
|
||||
while True:
|
||||
refreshRedis()
|
||||
start = time.time()
|
||||
# Do the thing
|
||||
pointsList = spectrum_10()
|
||||
print( linelistToPoints(lineList), flush=True )
|
||||
looptime = time.time() - start
|
||||
# debug(name+" looptime:"+str(looptime))
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
# debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
except EOFError:
|
||||
debug(name+" break")# no more information
|
||||
|
||||
288
generators/redilysis_particles.py
Executable file
288
generators/redilysis_particles.py
Executable file
|
|
@ -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
|
||||
94
generators/text.py
Normal file
94
generators/text.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
Experimental Laserized Turtle graphics library
|
||||
|
||||
See turtle1.py for example
|
||||
|
||||
pip3 install Hershey-Fonts
|
||||
|
||||
v0.1.0
|
||||
|
||||
Font list :
|
||||
'futural', 'astrology', 'cursive', 'cyrilc_1', 'cyrillic', 'futuram', 'gothgbt', 'gothgrt',
|
||||
'gothiceng', 'gothicger', 'gothicita', 'gothitt', 'greek', 'greekc', 'greeks', 'japanese',
|
||||
'markers', 'mathlow', 'mathupp', 'meteorology', 'music', 'rowmand', 'rowmans', 'rowmant',
|
||||
'scriptc', 'scripts', 'symbolic', 'timesg', 'timesi', 'timesib', 'timesr', 'timesrb'
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
from HersheyFonts import HersheyFonts
|
||||
|
||||
name="generator::text"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Text 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")
|
||||
argsparser.add_argument("-t","--text",help="Text to display",default="hello",type=str)
|
||||
argsparser.add_argument("-p","--police",help="Herschey font to use",default="futural",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
|
||||
text = args.text
|
||||
fontname = args.police
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
# Useful variables init.
|
||||
white = rgb2int((255,255,255))
|
||||
red = rgb2int((255,0,0))
|
||||
blue = rgb2int((0,0,255))
|
||||
green = rgb2int((0,255,0))
|
||||
|
||||
color = 65280
|
||||
|
||||
shape =[]
|
||||
|
||||
Allfonts = ['futural', 'astrology', 'cursive', 'cyrilc_1', 'cyrillic', 'futuram', 'gothgbt', 'gothgrt', 'gothiceng', 'gothicger', 'gothicita', 'gothitt', 'greek', 'greekc', 'greeks', 'japanese', 'markers', 'mathlow', 'mathupp', 'meteorology', 'music', 'rowmand', 'rowmans', 'rowmant', 'scriptc', 'scripts', 'symbolic', 'timesg', 'timesi', 'timesib', 'timesr', 'timesrb']
|
||||
|
||||
thefont = HersheyFonts()
|
||||
#thefont.load_default_font()
|
||||
thefont.load_default_font(fontname)
|
||||
thefont.normalize_rendering(120)
|
||||
|
||||
for (x1, y1), (x2, y2) in thefont.lines_for_text(text):
|
||||
shape.append([x1, -y1+400, color])
|
||||
shape.append([x2 ,-y2+400, color])
|
||||
|
||||
while True:
|
||||
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
#[[14.285714285714286, 100.0, 14.285714285714286, 25.0, 65280], [64.28571428571429, 100.0, 64.28571428571429, 25.0, 65280], [14.285714285714286, 64.28571428571429, 64.28571428571429, 64.28571428571429, 65280], [89.28571428571428, 53.57142857142858, 132.14285714285714, 53.57142857142858, 65280], [132.14285714285714, 53.57142857142858, 132.14285714285714, 60.714285714285715, 65280], [132.14285714285714, 60.714285714285715, 128.57142857142856, 67.85714285714286, 65280], [128.57142857142856, 67.85714285714286, 125.0, 71.42857142857143, 65280], [125.0, 71.42857142857143, 117.85714285714286, 75.0, 65280], [117.85714285714286, 75.0, 107.14285714285714, 75.0, 65280], [107.14285714285714, 75.0, 100.0, 71.42857142857143, 65280], [100.0, 71.42857142857143, 92.85714285714286, 64.28571428571429, 65280], [92.85714285714286, 64.28571428571429, 89.28571428571428, 53.57142857142858, 65280], [89.28571428571428, 53.57142857142858, 89.28571428571428, 46.42857142857143, 65280], [89.28571428571428, 46.42857142857143, 92.85714285714286, 35.714285714285715, 65280], [92.85714285714286, 35.714285714285715, 100.0, 28.571428571428573, 65280], [100.0, 28.571428571428573, 107.14285714285714, 25.0, 65280], [107.14285714285714, 25.0, 117.85714285714286, 25.0, 65280], [117.85714285714286, 25.0, 125.0, 28.571428571428573, 65280], [125.0, 28.571428571428573, 132.14285714285714, 35.714285714285715, 65280]]
|
||||
|
||||
175
generators/trckr.py
Normal file
175
generators/trckr.py
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
A Face tracker
|
||||
v0.1.0
|
||||
|
||||
Get all points fom redis /trckr/frame/WSclientID points
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
import redis
|
||||
import ast
|
||||
|
||||
name="generator::trckr"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Face tracking 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")
|
||||
argsparser.add_argument("-i","--id",help="Trckr client ID",default="0",type=str)
|
||||
argsparser.add_argument("-s","--server",help="redis server IP (127.0.0.1 by default)", type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
idclient = args.id
|
||||
|
||||
if args.server:
|
||||
redisIP = args.server
|
||||
else:
|
||||
redisIP = "127.0.0.1"
|
||||
|
||||
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
color = 65280
|
||||
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
# Useful variables init.
|
||||
white = rgb2int((255,255,255))
|
||||
red = rgb2int((255,0,0))
|
||||
blue = rgb2int((0,0,255))
|
||||
green = rgb2int((0,255,0))
|
||||
|
||||
#
|
||||
# Redis functions
|
||||
#
|
||||
|
||||
r = redis.StrictRedis(host=redisIP , port=6379, db=0)
|
||||
|
||||
# read from redis key
|
||||
def fromKey(keyname):
|
||||
|
||||
return r.get(keyname)
|
||||
|
||||
# Write to redis key
|
||||
def toKey(keyname,keyvalue):
|
||||
return r.set(keyname,keyvalue)
|
||||
|
||||
#
|
||||
# Trckr faces
|
||||
#
|
||||
|
||||
TrckrPts = [[159.39, 137.68], [155.12, 159.31], [155.56, 180.13], [159.81, 201.6], [170.48, 220.51], [187.46, 234.81], [208.4, 244.68], [229.46, 248.21], [246.44, 244.91], [259.69, 234.83], [270.95, 221.51], [278.54, 204.66], [283.53, 185.63], [286.27, 165.79], [284.72, 144.84], [280.06, 125.01], [274.35, 118.7], [260.71, 117.23], [249.52, 118.86], [182.04, 121.5], [193.63, 114.79], [210.24, 114.77], [222.35, 117.57], [190.6, 137.49], [203.59, 132.42], [214.75, 137.58], [203.04, 140.46], [203.32, 136.53], [272.45, 141.57], [263.33, 135.42], [250.31, 138.89], [262.15, 143.27], [261.99, 139.37], [235.82, 131.74], [221.87, 156.09], [213.66, 165.88], [219.28, 173.53], [236.3, 175.25], [249.02, 174.4], [254.22, 167.81], [248.83, 157.39], [237.94, 147.51], [227.01, 168.39], [245.68, 170.02], [204.94, 197.32], [217.56, 192.77], [228.27, 190.55], [234.66, 192.19], [240.47, 191.09], [247.96, 193.87], [254.52, 199.19], [249.35, 204.25], [242.74, 207.16], [233.2, 207.87], [222.13, 206.52], [212.44, 203.09], [220.34, 198.74], [233.31, 200.04], [244.0, 199.6], [244.27, 197.8], [233.81, 197.44], [220.88, 196.99], [239.57, 162.69], [196.52, 133.86], [210.2, 133.98], [209.43, 139.41], [196.59, 139.47], [268.99, 137.59], [256.36, 136.02], [255.95, 141.5], [267.9, 142.85]]
|
||||
toKey('/trckr/frame/0',str(TrckrPts))
|
||||
|
||||
# get absolute face position points
|
||||
def getPART(TrckrPts, pose_points):
|
||||
|
||||
dots = []
|
||||
#debug(pose_points)
|
||||
#debug(TrckrPts)
|
||||
for dot in pose_points:
|
||||
dots.append((TrckrPts[dot][0], TrckrPts[dot][1],0))
|
||||
#debug(dots)
|
||||
return dots
|
||||
|
||||
|
||||
# Face keypoints
|
||||
def face(TrckrPts):
|
||||
pose_points = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def browL(TrckrPts):
|
||||
pose_points = [15,16,17,18]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def browR(TrckrPts):
|
||||
pose_points = [22,21,20,19]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def eyeR(TrckrPts):
|
||||
pose_points = [25,64,24,63,23,66,26,65,25]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def eyeL(TrckrPts):
|
||||
pose_points = [28,67,29,68,30,69,31,28]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def pupR(TrckrPts):
|
||||
pose_points = [27]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def pupL(TrckrPts):
|
||||
pose_points = [32]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
|
||||
def nose1(TrckrPts):
|
||||
pose_points = [62,41,33]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def nose2(TrckrPts):
|
||||
pose_points = [40,39,38,43,37,42,36,35,34]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def mouth(TrckrPts):
|
||||
pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def mouthfull(TrckrPts):
|
||||
pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50,59,60,61,44,56,57,58,50]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
start = time.time()
|
||||
shape =[]
|
||||
points = ast.literal_eval(fromKey('/trckr/frame/'+idclient).decode('ascii'))
|
||||
shape.append(browL(points))
|
||||
shape.append(eyeL(points))
|
||||
shape.append(browR(points))
|
||||
shape.append(eyeR(points))
|
||||
shape.append(pupL(points))
|
||||
shape.append(pupR(points))
|
||||
shape.append(nose1(points))
|
||||
shape.append(nose2(points))
|
||||
shape.append(mouthfull(points))
|
||||
line = str(shape)
|
||||
line = line.replace("(",'[')
|
||||
line = line.replace(")",']')
|
||||
line = "[{}]".format(line)
|
||||
print(line, flush=True);
|
||||
#debug(shape)
|
||||
#print(shape, flush=True);
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
194
generators/tunnel.py
Executable file
194
generators/tunnel.py
Executable file
|
|
@ -0,0 +1,194 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Woooh! I'm progressing in a tunnel !
|
||||
v0.1.0
|
||||
|
||||
Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import math
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
name="generator::tunnel"
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="tunnel generator")
|
||||
argsparser.add_argument("-c","--color",help="Color",default=65280,type=int)
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-i","--interval",help="point per shape interval",default=30,type=int)
|
||||
argsparser.add_argument("-m","--max-size",help="maximum size for objects",default=400,type=int)
|
||||
argsparser.add_argument("-r","--randomize",help="center randomization",default=5,type=int)
|
||||
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int)
|
||||
argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int)
|
||||
|
||||
args = argsparser.parse_args()
|
||||
centerX = args.centerX
|
||||
centerY = args.centerY
|
||||
color = args.color
|
||||
fps = args.fps
|
||||
interval = args.interval
|
||||
max_size = args.max_size
|
||||
randomize = args.randomize
|
||||
speed = args.speed
|
||||
verbose = args.verbose
|
||||
|
||||
origSpeed = speed
|
||||
optimal_looptime = 1 / fps
|
||||
square = [
|
||||
[-1,1],
|
||||
[1,1],
|
||||
[1,-1],
|
||||
[-1,-1],
|
||||
[-1,1]
|
||||
]
|
||||
|
||||
circle = [[1,0],
|
||||
[0.9238795325112867,0.3826834323650898],
|
||||
[0.7071067811865476,0.7071067811865475],
|
||||
[0.38268343236508984,0.9238795325112867],
|
||||
[0,1.0],
|
||||
[-0.3826834323650897,0.9238795325112867],
|
||||
[-0.7071067811865475,0.7071067811865476],
|
||||
[-0.9238795325112867,0.3826834323650899],
|
||||
[-1.0,0],
|
||||
[-0.9238795325112868,-0.38268343236508967],
|
||||
[-0.7071067811865477,-0.7071067811865475],
|
||||
[-0.38268343236509034,-0.9238795325112865],
|
||||
[0,-1.0],
|
||||
[0.38268343236509,-0.9238795325112866],
|
||||
[0.707106781186548,-0.707106781186547],
|
||||
[0.9238795325112872,-0.3826834323650887],
|
||||
[1,0]]
|
||||
|
||||
shape = circle
|
||||
currentCenter = [centerX, centerY]
|
||||
centerVector= [0,0]
|
||||
# tweak random basis
|
||||
if randomize % 2 == 1:
|
||||
randomize += 1
|
||||
debug(name,"randomize:{}".format(randomize))
|
||||
centerRand = int(math.sqrt(randomize) / 4 ) + 1
|
||||
debug( name, "centerRand:{}".format(centerRand ) )
|
||||
class polylineGenerator( object ):
|
||||
|
||||
def __init__( self ):
|
||||
self.polylineList = [[0,[currentCenter[0],currentCenter[1]]]]
|
||||
self.buf = []
|
||||
|
||||
def init(self):
|
||||
finished = False
|
||||
while not finished:
|
||||
finished = self.increment()
|
||||
debug(name,"init done:{}".format(self.polylineList))
|
||||
def draw( self ):
|
||||
self.buf = []
|
||||
for it_pl, infoList in enumerate(self.polylineList):
|
||||
size = infoList[0]
|
||||
center = infoList[1]
|
||||
for it_sqr, point in enumerate(shape):
|
||||
x = int( center[0] + point[0]*size )
|
||||
y = int( center[1] + point[1]*size )
|
||||
# Add an invisible point in first location
|
||||
if 0 == it_sqr:
|
||||
self.buf.append([x,y,0])
|
||||
self.buf.append([x,y,color])
|
||||
#debug( name, "buf size:", str(len(self.buf)) )
|
||||
return self.buf
|
||||
|
||||
def increment(self):
|
||||
global speed
|
||||
self.buffer = []
|
||||
min_size = 9999
|
||||
delList = []
|
||||
if randomize :
|
||||
# Change the vector
|
||||
centerVector[0] += random.randrange( -centerRand,centerRand )
|
||||
centerVector[1] += random.randrange( -centerRand,centerRand )
|
||||
# Modify the vector if it is over the limit
|
||||
if currentCenter[0] + centerVector[0] >= centerX + randomize or currentCenter[0] + centerVector[0] <= centerX - randomize:
|
||||
centerVector[0] = 0
|
||||
if currentCenter[1] + centerVector[1] >= centerY + randomize or currentCenter[1] +centerVector[1] <= centerY - randomize:
|
||||
centerVector[1] = 0
|
||||
currentCenter[0] += centerVector[0]
|
||||
currentCenter[1] += centerVector[1]
|
||||
# Change speed
|
||||
speed += int( random.randrange( int(-origSpeed),origSpeed ) )
|
||||
if speed < origSpeed :
|
||||
speed = origSpeed
|
||||
elif speed > (origSpeed + randomize / 2) :
|
||||
speed = origSpeed + randomize / 2
|
||||
#debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed))
|
||||
|
||||
for i, shapeInfo in enumerate(self.polylineList):
|
||||
size = shapeInfo[0]
|
||||
# Augment speed with size
|
||||
"""
|
||||
size = 0 : += sqrt(speed)
|
||||
size = half max size : +=speed
|
||||
|
||||
"""
|
||||
if size < max_size / 4:
|
||||
size += math.pow(speed, 0.1)
|
||||
elif size < max_size / 3:
|
||||
size += math.pow(speed, 0.25)
|
||||
elif size < max_size / 2:
|
||||
size += math.pow(speed, 0.5)
|
||||
else:
|
||||
size += math.pow(speed, 1.25)
|
||||
if size < min_size : min_size = size
|
||||
if size > max_size : delList.append(i)
|
||||
self.polylineList[i][0] = size
|
||||
for i in delList:
|
||||
del self.polylineList[i]
|
||||
#debug(name, "polyline:",self.polylineList)
|
||||
if min_size >= interval:
|
||||
debug(name, "new shape")
|
||||
self.polylineList.append([0,[currentCenter[0],currentCenter[1]]])
|
||||
|
||||
# Return True if we delete a shape
|
||||
|
||||
if len(delList):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
pgen = polylineGenerator()
|
||||
pgen.init()
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
|
||||
# Generate
|
||||
pgen.increment()
|
||||
|
||||
# send
|
||||
pl = pgen.draw()
|
||||
print(pl, flush=True)
|
||||
#debug(name,"output:{}".format(pl))
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
#debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
657
generators/turtle.py
Normal file
657
generators/turtle.py
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Turtle library laser emulation
|
||||
v0.1b
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
import math
|
||||
|
||||
from HersheyFonts import HersheyFonts
|
||||
|
||||
|
||||
name="generator::turtle"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Turtle graphics 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")
|
||||
argsparser.add_argument("-x","--LasCenterX",help="geometrical center X position",default=350,type=int)
|
||||
argsparser.add_argument("-y","--LasCenterY",help="geometrical center Y position",default=350,type=int)
|
||||
argsparser.add_argument("-p","--police",help="Herschey font to use",default="futural",type=str)
|
||||
argsparser.add_argument("-m","--mode",help="Mode to use : ",default="clitools",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
mode = args.mode
|
||||
LasCenterX = args.LasCenterX
|
||||
LasCenterY = args.LasCenterY
|
||||
fontname = args.police
|
||||
|
||||
Allfonts = ['futural', 'astrology', 'cursive', 'cyrilc_1', 'cyrillic', 'futuram', 'gothgbt', 'gothgrt', 'gothiceng', 'gothicger', 'gothicita', 'gothitt', 'greek', 'greekc', 'greeks', 'japanese', 'markers', 'mathlow', 'mathupp', 'meteorology', 'music', 'rowmand', 'rowmans', 'rowmant', 'scriptc', 'scripts', 'symbolic', 'timesg', 'timesi', 'timesib', 'timesr', 'timesrb']
|
||||
|
||||
thefont = HersheyFonts()
|
||||
#thefont.load_default_font()
|
||||
thefont.load_default_font(fontname)
|
||||
thefont.normalize_rendering(120)
|
||||
|
||||
CurrentColor = 255
|
||||
CurrentAngle = 0.0
|
||||
CurrentX = 0.0
|
||||
CurrentY = 0.0
|
||||
|
||||
shape = []
|
||||
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
|
||||
#
|
||||
# Color functions
|
||||
#
|
||||
|
||||
# input hexcode = '0xff00ff'
|
||||
def hex2rgb(hexcode):
|
||||
|
||||
hexcode = hexcode[2:]
|
||||
return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4))
|
||||
#return tuple(map(ord,hexcode[1:].decode('hex')))
|
||||
|
||||
# input rgb=(255,0,255) output '0xff00ff'
|
||||
def rgb2hex(rgb):
|
||||
return '0x%02x%02x%02x' % tuple(rgb)
|
||||
|
||||
#def rgb2hex(r, g, b):
|
||||
# return hex((r << 16) + (g << 8) + b)
|
||||
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
#def rgb2int(r,g,b):
|
||||
# return int('0x%02x%02x%02x' % (r,g,b),0)
|
||||
|
||||
def int2rgb(intcode):
|
||||
#hexcode = '0x{0:06X}'.format(intcode)
|
||||
hexcode = '{0:06X}'.format(intcode)
|
||||
return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4))
|
||||
|
||||
#
|
||||
# Turtle
|
||||
#
|
||||
|
||||
def fd(distance):
|
||||
forward(distance)
|
||||
def forward(distance):
|
||||
global CurrentX, CurrentY, shape
|
||||
#Move the turtle forward by the specified distance, in the direction the turtle is headed.
|
||||
|
||||
rad = CurrentAngle * math.pi / 180
|
||||
CurrentX = distance * math.cos(rad) + CurrentX
|
||||
CurrentY = distance * math.sin(rad) + CurrentY
|
||||
|
||||
shape.append([CurrentX + LasCenterX , CurrentY + LasCenterY , CurrentColor])
|
||||
|
||||
|
||||
def back(distance):
|
||||
backward(distance)
|
||||
def bk(distance):
|
||||
backward(distance)
|
||||
def backward(distance):
|
||||
global CurrentX, CurrentY, shape
|
||||
#Move the turtle backward by distance, opposite to the direction the turtle is headed. Do not change the turtle’s heading.
|
||||
|
||||
rad = (CurrentAngle+180) * math.pi / 180
|
||||
CurrentX = distance * math.cos(rad) + CurrentX
|
||||
CurrentY = distance * math.sin(rad) + CurrentY
|
||||
|
||||
shape.append([CurrentX + LasCenterX, CurrentY + LasCenterY, CurrentColor])
|
||||
|
||||
|
||||
def right(angle):
|
||||
rt(angle)
|
||||
def rt(angle):
|
||||
global CurrentAngle
|
||||
#Turn turtle right by angle units. (Units are by default degrees, but can be set via the degrees() and radians() functions.) Angle orientation depends on the turtle mode, see mode().
|
||||
|
||||
CurrentAngle = CurrentAngle + angle
|
||||
|
||||
|
||||
def left(angle):
|
||||
lt(angle)
|
||||
def lt(angle):
|
||||
global CurrentAngle
|
||||
#Turn turtle left by angle units. (Units are by default degrees, but can be set via the degrees() and radians() functions.) Angle orientation depends on the turtle mode, see mode().
|
||||
|
||||
CurrentAngle = CurrentAngle - angle
|
||||
|
||||
def goto(x, y=None):
|
||||
setposition(x, y=None)
|
||||
def setpos(x, y=None):
|
||||
setposition(x, y=None)
|
||||
def setposition(x, y=None):
|
||||
global CurrentX, CurrentY, shape
|
||||
|
||||
#If y is None, x must be a pair of coordinates or a Vec2D (e.g. as returned by pos()).
|
||||
# Move turtle to an absolute position. If the pen is down, draw line. Do not change the turtle’s orientation.
|
||||
|
||||
CurrentX = x
|
||||
CurrentY = y
|
||||
shape.append([CurrentX + LasCenterX, CurrentY + LasCenterY, CurrentColor])
|
||||
|
||||
|
||||
def setx(x):
|
||||
global CurrentX
|
||||
#Set the turtle’s first coordinate to x, leave second coordinate unchanged.
|
||||
CurrentX = x
|
||||
|
||||
|
||||
def sety(y):
|
||||
global CurrentY
|
||||
#Set the turtle’s second coordinate to y, leave first coordinate unchanged.
|
||||
CurrentY = y
|
||||
|
||||
|
||||
def setheading(to_angle):
|
||||
global CurrentAngle
|
||||
#Parameters: to_angle – a number (integer or float)
|
||||
CurrentAngle = to_angle
|
||||
|
||||
def home():
|
||||
global CurrentX, CurrentY, CurrentAngle , shape
|
||||
#Move turtle to the origin – coordinates (0,0) – and set its heading to its start-orientation (which depends on the mode, see mode()).
|
||||
CurrentX = 0.0
|
||||
CurrentY = 0.0
|
||||
CurrentAngle = 0.0
|
||||
shape.append([CurrentX + LasCenterX, CurrentY + LasCenterY, CurrentColor])
|
||||
|
||||
|
||||
def circle(radius, extent=None, steps=None):
|
||||
#Draw a circle with given radius. The center is radius units left of the turtle; extent – an angle – determines which part of the circle is drawn. If extent is not given, draw the entire circle. If extent is not a full circle, one endpoint of the arc is the current pen position. Draw the arc in counterclockwise direction if radius is positive, otherwise in clockwise direction. Finally the direction of the turtle is changed by the amount of extent.
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
>>> turtle.home()
|
||||
>>> turtle.position()
|
||||
(0.00,0.00)
|
||||
>>> turtle.heading()
|
||||
0.0
|
||||
>>> turtle.circle(50)
|
||||
>>> turtle.position()
|
||||
(-0.00,0.00)
|
||||
>>> turtle.heading()
|
||||
0.0
|
||||
>>> turtle.circle(120, 180) # draw a semicircle
|
||||
>>> turtle.position()
|
||||
(0.00,240.00)
|
||||
>>> turtle.heading()
|
||||
180.0
|
||||
'''
|
||||
|
||||
def dot(size=None, *color):
|
||||
#Draw a circular dot with diameter size, using color. If size is not given, the maximum of pensize+4 and 2*pensize is used.
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
'''
|
||||
>>> turtle.home()
|
||||
>>> turtle.dot()
|
||||
>>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50)
|
||||
>>> turtle.position()
|
||||
(100.00,-0.00)
|
||||
>>> turtle.heading()
|
||||
0.0
|
||||
'''
|
||||
|
||||
def stamp():
|
||||
|
||||
#Stamp a copy of the turtle shape onto the canvas at the current turtle position. Return a stamp_id for that stamp, which can be used to delete it by calling clearstamp(stamp_id).
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
>>> turtle.color("blue")
|
||||
>>> turtle.stamp()
|
||||
11
|
||||
>>> turtle.fd(50)
|
||||
'''
|
||||
|
||||
def clearstamp(stampid):
|
||||
#Delete stamp with given stampid.
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
>>> turtle.position()
|
||||
(150.00,-0.00)
|
||||
>>> turtle.color("blue")
|
||||
>>> astamp = turtle.stamp()
|
||||
>>> turtle.fd(50)
|
||||
>>> turtle.position()
|
||||
(200.00,-0.00)
|
||||
>>> turtle.clearstamp(astamp)
|
||||
>>> turtle.position()
|
||||
(200.00,-0.00)
|
||||
'''
|
||||
|
||||
def clearstamps(n=None):
|
||||
#Delete all or first/last n of turtle’s stamps. If n is None, delete all stamps, if n > 0 delete first n stamps, else if n < 0 delete last n stamps.
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
'''
|
||||
>>> for i in range(8):
|
||||
... turtle.stamp(); turtle.fd(30)
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
>>> turtle.clearstamps(2)
|
||||
>>> turtle.clearstamps(-2)
|
||||
>>> turtle.clearstamps()
|
||||
'''
|
||||
|
||||
def undo():
|
||||
#Undo (repeatedly) the last turtle action(s). Number of available undo actions is determined by the size of the undobuffer.
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
>>> for i in range(4):
|
||||
... turtle.fd(50); turtle.lt(80)
|
||||
...
|
||||
>>> for i in range(8):
|
||||
... turtle.undo()
|
||||
'''
|
||||
|
||||
def speed(speed=None):
|
||||
#Set the turtle’s speed to an integer value in the range 0..10. If no argument is given, return current speed.
|
||||
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
'''
|
||||
If input is a number greater than 10 or smaller than 0.5, speed is set to 0. Speedstrings are mapped to speedvalues as follows:
|
||||
|
||||
“fastest”: 0
|
||||
“fast”: 10
|
||||
“normal”: 6
|
||||
“slow”: 3
|
||||
“slowest”: 1
|
||||
|
||||
Speeds from 1 to 10 enforce increasingly faster animation of line drawing and turtle turning.
|
||||
|
||||
Attention: speed = 0 means that no animation takes place. forward/back makes turtle jump and likewise left/right make the turtle turn instantly.
|
||||
>>>
|
||||
|
||||
>>> turtle.speed()
|
||||
3
|
||||
>>> turtle.speed('normal')
|
||||
>>> turtle.speed()
|
||||
6
|
||||
>>> turtle.speed(9)
|
||||
>>> turtle.speed()
|
||||
9
|
||||
'''
|
||||
|
||||
def position():
|
||||
pos()
|
||||
def pos():
|
||||
#Return the turtle’s current location (x,y) (as a Vec2D vector).
|
||||
return (CurrentX,CurrentY)
|
||||
|
||||
def towards(x, y=None):
|
||||
#Return the angle between the line from turtle position to position specified by (x,y), the vector or the other turtle. This depends on the turtle’s start orientation which depends on the mode - “standard”/”world” or “logo”).
|
||||
|
||||
# Currently only toward an x,y point
|
||||
|
||||
xDiff = x - CurrentX
|
||||
yDiff = y - CurrentY
|
||||
return degrees(atan2(yDiff, xDiff))
|
||||
|
||||
|
||||
def xcor():
|
||||
#Return the turtle’s x coordinate.
|
||||
return CurrentX
|
||||
|
||||
|
||||
def ycor():
|
||||
#Return the turtle’s y coordinate.
|
||||
return CurrentY
|
||||
|
||||
|
||||
def heading():
|
||||
#Return the turtle’s current heading (value depends on the turtle mode, see mode())
|
||||
|
||||
return CurrentAngle
|
||||
|
||||
|
||||
def distance(x, y=None):
|
||||
#Return the distance from the turtle to (x,y), the given vector, or the given other turtle, in turtle step units.
|
||||
|
||||
dist = math.sqrt((x - CurrentY)**2 + (y - CurrentY)**2)
|
||||
return dist
|
||||
|
||||
|
||||
def degrees(fullcircle=360.0):
|
||||
#Set angle measurement units, i.e. set number of “degrees” for a full circle. Default value is 360 degrees.
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(90)
|
||||
>>> turtle.heading()
|
||||
90.0
|
||||
|
||||
Change angle measurement unit to grad (also known as gon,
|
||||
grade, or gradian and equals 1/100-th of the right angle.)
|
||||
>>> turtle.degrees(400.0)
|
||||
>>> turtle.heading()
|
||||
100.0
|
||||
>>> turtle.degrees(360)
|
||||
>>> turtle.heading()
|
||||
90.0
|
||||
'''
|
||||
def radians():
|
||||
#Set the angle measurement units to radians. Equivalent to degrees(2*math.pi).
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
'''
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(90)
|
||||
>>> turtle.heading()
|
||||
90.0
|
||||
>>> turtle.radians()
|
||||
>>> turtle.heading()
|
||||
1.5707963267948966
|
||||
'''
|
||||
|
||||
def pendown():
|
||||
down()
|
||||
def pd():
|
||||
down()
|
||||
def down():
|
||||
global CurrentColor
|
||||
#Pull the pen down – drawing when moving.
|
||||
CurrentColor = Color
|
||||
|
||||
|
||||
def penup():
|
||||
up()
|
||||
def pu():
|
||||
up()
|
||||
def up():
|
||||
#Pull the pen up – no drawing when moving.
|
||||
global CurrentColor
|
||||
|
||||
CurrentColor = 0
|
||||
|
||||
|
||||
def pensize(width=None):
|
||||
width(width=None)
|
||||
def width(width=None):
|
||||
#Set the line thickness to width or return it. If resizemode is set to “auto” and turtleshape is a polygon, that polygon is drawn with the same line thickness. If no argument is given, the current pensize is returned.
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
>>> turtle.pensize()
|
||||
1
|
||||
>>> turtle.pensize(10) # from here on lines of width 10 are drawn
|
||||
'''
|
||||
|
||||
def pen(pen=None, **pendict):
|
||||
#Return or set the pen’s attributes in a “pen-dictionary” with the following key/value pairs:
|
||||
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
“shown”: True/False
|
||||
“pendown”: True/False
|
||||
“pencolor”: color-string or color-tuple
|
||||
“fillcolor”: color-string or color-tuple
|
||||
“pensize”: positive number
|
||||
“speed”: number in range 0..10
|
||||
“resizemode”: “auto” or “user” or “noresize”
|
||||
“stretchfactor”: (positive number, positive number)
|
||||
“outline”: positive number
|
||||
“tilt”: number
|
||||
|
||||
This dictionary can be used as argument for a subsequent call to pen() to restore the former pen-state. Moreover one or more of these attributes can be provided as keyword-arguments. This can be used to set several pen attributes in one statement.
|
||||
>>>
|
||||
|
||||
>>> turtle.pen(fillcolor="black", pencolor="red", pensize=10)
|
||||
>>> sorted(turtle.pen().items())
|
||||
[('fillcolor', 'black'), ('outline', 1), ('pencolor', 'red'),
|
||||
('pendown', True), ('pensize', 10), ('resizemode', 'noresize'),
|
||||
('shearfactor', 0.0), ('shown', True), ('speed', 9),
|
||||
('stretchfactor', (1.0, 1.0)), ('tilt', 0.0)]
|
||||
>>> penstate=turtle.pen()
|
||||
>>> turtle.color("yellow", "")
|
||||
>>> turtle.penup()
|
||||
>>> sorted(turtle.pen().items())[:3]
|
||||
[('fillcolor', ''), ('outline', 1), ('pencolor', 'yellow')]
|
||||
>>> turtle.pen(penstate, fillcolor="green")
|
||||
>>> sorted(turtle.pen().items())[:3]
|
||||
[('fillcolor', 'green'), ('outline', 1), ('pencolor', 'red')]
|
||||
'''
|
||||
|
||||
def isdown():
|
||||
#Return True if pen is down, False if it’s up.
|
||||
if CurrentColor != 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def pencolor(*args):
|
||||
global CurrentColor
|
||||
'''
|
||||
Return or set the pencolor.
|
||||
|
||||
Four input formats are allowed:
|
||||
|
||||
pencolor()
|
||||
Return the current pencolor as color specification string or as a tuple (see example). May be used as input to another color/pencolor/fillcolor call.
|
||||
pencolor(colorstring)
|
||||
Set pencolor to colorstring, which is a Tk color specification string, such as "red", "yellow", or "#33cc8c".
|
||||
pencolor((r, g, b))
|
||||
Set pencolor to the RGB color represented by the tuple of r, g, and b. Each of r, g, and b must be in the range 0..colormode, where colormode is either 1.0 or 255 (see colormode()).
|
||||
pencolor(r, g, b)
|
||||
|
||||
Set pencolor to the RGB color represented by r, g, and b. Each of r, g, and b must be in the range 0..colormode.
|
||||
|
||||
If turtleshape is a polygon, the outline of that polygon is drawn with the newly set pencolor.
|
||||
'''
|
||||
#print(args, len(args))
|
||||
if len(args) == 1:
|
||||
colors = args[0]
|
||||
#print(colors)
|
||||
if colors[0]=="#":
|
||||
CurrentColor = hex2int(colors)
|
||||
else:
|
||||
CurrentColor = rgb2int(colors)
|
||||
print("CurrentColor:",CurrentColor)
|
||||
|
||||
else:
|
||||
print(int2rgb(CurrentColor))
|
||||
return int2rgb(CurrentColor)
|
||||
'''
|
||||
>>>
|
||||
|
||||
>>> colormode()
|
||||
1.0
|
||||
>>> turtle.pencolor()
|
||||
'red'
|
||||
>>> turtle.pencolor("brown")
|
||||
>>> turtle.pencolor()
|
||||
'brown'
|
||||
>>> tup = (0.2, 0.8, 0.55)
|
||||
>>> turtle.pencolor(tup)
|
||||
>>> turtle.pencolor()
|
||||
(0.2, 0.8, 0.5490196078431373)
|
||||
>>> colormode(255)
|
||||
>>> turtle.pencolor()
|
||||
(51.0, 204.0, 140.0)
|
||||
>>> turtle.pencolor('#32c18f')
|
||||
>>> turtle.pencolor()
|
||||
(50.0, 193.0, 143.0)
|
||||
'''
|
||||
def fillcolor(*args):
|
||||
# Return or set the fillcolor.
|
||||
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
|
||||
|
||||
def color(*args):
|
||||
global CurrentColor
|
||||
#Return or set pencolor and fillcolor.
|
||||
|
||||
if len(*args) ==2:
|
||||
colors = args
|
||||
if colors[0][0]=="#":
|
||||
CurrentColor = hex2int(colors[0])
|
||||
|
||||
else:
|
||||
print(int2rgb(CurrentColor),(0,0,0))
|
||||
return (int2rgb(CurrentColor),(0,0,0))
|
||||
|
||||
#rgb2int(rgb)
|
||||
'''
|
||||
Several input formats are allowed. They use 0 to 3 arguments as follows:
|
||||
|
||||
color()
|
||||
Return the current pencolor and the current fillcolor as a pair of color specification strings or tuples as returned by pencolor() and fillcolor().
|
||||
color(colorstring), color((r,g,b)), color(r,g,b)
|
||||
Inputs as in pencolor(), set both, fillcolor and pencolor, to the given value.
|
||||
color(colorstring1, colorstring2), color((r1,g1,b1), (r2,g2,b2))
|
||||
|
||||
Equivalent to pencolor(colorstring1) and fillcolor(colorstring2) and analogously if the other input format is used.
|
||||
|
||||
If turtleshape is a polygon, outline and interior of that polygon is drawn with the newly set colors.
|
||||
|
||||
>>>
|
||||
|
||||
>>> turtle.color("red", "green")
|
||||
>>> turtle.color()
|
||||
('red', 'green')
|
||||
>>> color("#285078", "#a0c8f0")
|
||||
>>> color()
|
||||
((40.0, 80.0, 120.0), (160.0, 200.0, 240.0))
|
||||
|
||||
'''
|
||||
|
||||
def filling():
|
||||
# Return fillstate (True if filling, False else).
|
||||
return False
|
||||
|
||||
def begin_fill():
|
||||
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
def end_fill():
|
||||
#Fill the shape drawn after the last call to begin_fill().
|
||||
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
|
||||
|
||||
def reset():
|
||||
#Delete the turtle’s drawings from the screen, re-center the turtle and set variables to the default values.
|
||||
global shape
|
||||
|
||||
clear()
|
||||
home()
|
||||
|
||||
def clear():
|
||||
#Delete the turtle’s drawings from the screen. Do not move turtle. State and position of the turtle as well as drawings of other turtles are not affected.
|
||||
global shape
|
||||
shape = []
|
||||
|
||||
|
||||
def write(arg, move=False, align="left", font=("Arial", 8, "normal")):
|
||||
global shape
|
||||
'''
|
||||
Parameters:
|
||||
|
||||
arg – object to be written to the TurtleScreen
|
||||
move – True/False
|
||||
align – one of the strings “left”, “center” or right”
|
||||
font – a triple (fontname, fontsize, fonttype)
|
||||
|
||||
Write text - the string representation of arg - at the current turtle position according to align (“left”, “center” or right”) and with the given font. If move is true, the pen is moved to the bottom-right corner of the text. By default, move is False.
|
||||
'''
|
||||
for (x1, y1), (x2, y2) in thefont.lines_for_text(arg):
|
||||
shape.append([x1, -y1+400, color])
|
||||
shape.append([x2 ,-y2+400, color])
|
||||
|
||||
'''
|
||||
>>> turtle.write("Home = ", True, align="center")
|
||||
>>> turtle.write((0,0), True)
|
||||
'''
|
||||
|
||||
def hideturtle():
|
||||
ht()
|
||||
def ht():
|
||||
#Make the turtle invisible. It’s a good idea to do this while you’re in the middle of doing some complex drawing, because hiding the turtle speeds up the drawing observably.
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
#>>> turtle.hideturtle()
|
||||
|
||||
def showturtle():
|
||||
st()
|
||||
def st():
|
||||
|
||||
#Make the turtle visible.
|
||||
print("Not yet in Laser turtle.")
|
||||
|
||||
|
||||
|
||||
def delay(delay=None):
|
||||
|
||||
#Set or return the drawing delay in milliseconds. (This is approximately the time interval between two consecutive canvas updates.) The longer the drawing delay, the slower the animation.
|
||||
print("Not yet in Laser turtle.")
|
||||
'''
|
||||
Optional argument:
|
||||
|
||||
>>> screen.delay()
|
||||
10
|
||||
>>> screen.delay(5)
|
||||
>>> screen.delay()
|
||||
5
|
||||
'''
|
||||
|
||||
|
||||
def mainloop():
|
||||
done()
|
||||
def done():
|
||||
#Starts event loop - calling Tkinter’s mainloop function. Must be the last statement in a turtle graphics program. Must not be used if a script is run from within IDLE in -n mode (No subprocess) - for interactive use of turtle graphics.
|
||||
while True:
|
||||
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
def window_height():
|
||||
|
||||
#Return the height of the turtle window.
|
||||
return LasCenterX * 2
|
||||
|
||||
def window_width():
|
||||
|
||||
#Return the width of the turtle window.
|
||||
return LasCenterY*2
|
||||
|
||||
|
||||
19
generators/turtle1.py
Normal file
19
generators/turtle1.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
Example using experimental Laserized Turtle graphics library
|
||||
|
||||
'''
|
||||
|
||||
from turtle import *
|
||||
|
||||
pencolor((255,0,0))
|
||||
|
||||
for i in range(4):
|
||||
forward(100)
|
||||
right(90)
|
||||
|
||||
done()
|
||||
Loading…
Add table
Add a link
Reference in a new issue