From 8164320694cd8f4daa10b21ac793851e710a2ede Mon Sep 17 00:00:00 2001 From: Lapin Date: Thu, 17 Dec 2020 20:18:32 +0100 Subject: [PATCH 1/4] [fix] to avoid temporary vim's file --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 06df7ba..4cf0f62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -.*swp* +.*sw* *__pycache__ www/config.js + + From f3314441d3988355b474d5feebf955def029d480 Mon Sep 17 00:00:00 2001 From: Lapin Date: Thu, 17 Dec 2020 20:21:04 +0100 Subject: [PATCH 2/4] [feat] drawing_optimisation: in progess the feature implement a paper: https://art-science.org/journal/v7n4/v7n4pp155/artsci-v7n4pp155.pdf there is some generator to test the optimisation in: ./clitools/generators/drawingTests/ Now, all the optimisation will be in ./libs3/plotOptimizer.py in ./libs3/tracer3.py the adding of point is avoid an will be replace by the optimisation from the paper --- .../drawingTests/angleOptimization.py | 98 +++++++++++++++ .../drawingTests/conected_component.py | 117 ++++++++++++++++++ .../generators/drawingTests/endingPoint.py | 77 ++++++++++++ .../drawingTests/order_optimization.py | 84 +++++++++++++ libs3/plotOptimizer.py | 93 ++++++++++++++ libs3/tracer3.py | 51 ++++---- 6 files changed, 493 insertions(+), 27 deletions(-) create mode 100644 clitools/generators/drawingTests/angleOptimization.py create mode 100644 clitools/generators/drawingTests/conected_component.py create mode 100644 clitools/generators/drawingTests/endingPoint.py create mode 100644 clitools/generators/drawingTests/order_optimization.py create mode 100644 libs3/plotOptimizer.py diff --git a/clitools/generators/drawingTests/angleOptimization.py b/clitools/generators/drawingTests/angleOptimization.py new file mode 100644 index 0000000..c1ed478 --- /dev/null +++ b/clitools/generators/drawingTests/angleOptimization.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +This generator print different angle form 0 to 180 degres + +v0.1.0 + +LICENCE : CC + +by lapin (aka nipal) + +''' + +from __future__ import print_function +import time +import argparse +import sys +import math + +name="generator::endingPoint" + + +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)) + +width = 800 +height = 800 + +white = 0xFFFFFF +blank = 0 + +radius = 100 +offset_circles = 10 +beg_angle = 0 +end_angle = 90 +offset_angle = 10 + +angles_lines = [] +shape = [] + +def set_angles_lines(): + margin = radius + offset_circles + spacing_betwen = 2 * radius + offset_circles + circles_per_line = math.floor((width - margin) / spacing_betwen) + + for ang in range(beg_angle, end_angle + offset_angle, offset_angle): + nb = int(ang / offset_angle) + cx = margin + (nb % circles_per_line) * spacing_betwen + cy = margin + int(nb / circles_per_line) * spacing_betwen + + px = radius * math.cos(math.radians(ang)) + py = radius * math.sin(math.radians(ang)) + + # line up + angles_lines.append([-px + cx, py + cy, blank]) + angles_lines.append([-px + cx, py + cy, white]) + angles_lines.append([ cx, 2 + cy, white]) + angles_lines.append([ px + cx, py + cy, white]) + #angles_lines.append([ px + cx, py + cy, blank]) + + # line down + angles_lines.append([-px + cx, -py + cy, blank]) + angles_lines.append([-px + cx, -py + cy, white]) + angles_lines.append([ cx, -2 + cy, white]) + angles_lines.append([ px + cx, -py + cy, white]) + #angles_lines.append([ px + cx, -py + cy, blank]) + + +set_angles_lines() + +shape = angles_lines +# print(angles_lines) + +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)) + diff --git a/clitools/generators/drawingTests/conected_component.py b/clitools/generators/drawingTests/conected_component.py new file mode 100644 index 0000000..2038e21 --- /dev/null +++ b/clitools/generators/drawingTests/conected_component.py @@ -0,0 +1,117 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +This generator print a shape with 3 discinected component, 2 non eulerian and one eulerian. + +v0.1.0 + +LICENCE : CC + +by lapin (aka nipal) + +''' + +from __future__ import print_function +import time +import argparse +import sys +import math + +name="generator::endingPoint" + + +def debug(*args, **kwargs): + if( verbose == False ): + return + print(*args, file=sys.stderr, **kwargs) + +def debug2(*args, **kwargs): + 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)) + +width = 800 +height = 800 + +white = 0xFFFFFF +blank = 0 + +def shape_scale(shape, scale_factor): + new_shape = [] + + for p in shape: + new_shape.append([p[0] * scale_factor, p[1] * scale_factor, p[2]]) + return new_shape + +def shape_incr(shape, x, y): + new_shape = [] + + for p in shape: + new_shape.append([p[0] + x, p[1] + y, p[2]]) + return new_shape + +comp_a = [] +comp_b = [] +comp_c = [] + +comp_b.append([ 0, 3, blank]) +comp_b.append([ 0, 4, white]) +comp_b.append([ 0, 0, white]) +comp_b.append([ 3, 0, white]) +comp_b.append([ 3, 6, white]) +comp_b.append([ 3, 6, white]) +comp_b.append([ 3, 0, white]) +comp_b.append([ 3, 0, blank]) +comp_b.append([ 3, 0, white]) +comp_b.append([ 5, 4, white]) +comp_b.append([ 5, 4, blank]) + +comp_a.append([ 5, 17, blank]) +comp_a.append([ 5, 17, white]) +comp_a.append([ 0, 5, white]) +comp_a.append([12, 0, white]) +comp_a.append([17, 12, white]) +comp_a.append([ 5, 17, white]) +comp_a.append([ 5, 17, blank]) + +comp_c.append([-3, 5, blank]) +comp_c.append([-3, 5, white]) +comp_c.append([ 0, 4, white]) +comp_c.append([ 0, 0, white]) +comp_c.append([ 4, 0, white]) +comp_c.append([ 4, 4, white]) +comp_c.append([ 7, 5, white]) +comp_c.append([ 7, 5, blank]) + +comp_a = shape_scale(comp_a, 11) +comp_a = shape_incr(comp_a, 300, 75) + +comp_b = shape_scale(comp_b, 45) +comp_b = shape_incr(comp_b, 0, 300) + +comp_c = shape_scale(comp_c, 30) +comp_c = shape_incr(comp_c, 600, 300) + +shape = comp_a + comp_b + comp_c + +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)) + diff --git a/clitools/generators/drawingTests/endingPoint.py b/clitools/generators/drawingTests/endingPoint.py new file mode 100644 index 0000000..3cb0bf5 --- /dev/null +++ b/clitools/generators/drawingTests/endingPoint.py @@ -0,0 +1,77 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +This generator print 3 static vertical line. +The aim is to show The aim is to show the laser beam ignition time. +beam when ther is no optimisation + +v0.1.0 + +LICENCE : CC + +by lapin (aka nipal) + +''' + +from __future__ import print_function +import time +import argparse +import sys + +name="generator::endingPoint" + + +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)) + +white = 0xFFFFFF +blank = 0 +offset_y = 100 +offset_x = 50 + +begin_x = 200 +begin_y = 200 + +shape_factor = [ + [0, 0, white], + [0, 1, blank], + [1, 1, white], + [1, 0, blank], + [2, 0, white], + [2, 1, blank], + [2, 1, blank], +] + +shape = [] + +for point in shape_factor: + shape.append([begin_x + offset_x * point[0], + begin_y + offset_y * point[1], + point[2]]) + + +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)) + diff --git a/clitools/generators/drawingTests/order_optimization.py b/clitools/generators/drawingTests/order_optimization.py new file mode 100644 index 0000000..409c14e --- /dev/null +++ b/clitools/generators/drawingTests/order_optimization.py @@ -0,0 +1,84 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +This generator print a shape with best angle representation when the path is redraw + +v0.1.0 + +LICENCE : CC + +by lapin (aka nipal) + +''' + +from __future__ import print_function +import time +import argparse +import sys +import math + +name="generator::endingPoint" + + +def debug(*args, **kwargs): + if( verbose == False ): + return + print(*args, file=sys.stderr, **kwargs) + +def debug2(*args, **kwargs): + 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)) + +width = 800 +height = 800 + +white = 0xFFFFFF +blank = 0 + +point_offset = 250 + +point_width = 4 +point_list = [ + [8,7,6,10,7,3,6,2,7,11,6,9], + [5,6,1,], + [4,7,12,], + ] + +shape = [] + +# on ajoute des lilste de point +for l in point_list: + x = point_offset * ((l[0] - 1) % (point_width)) + y = point_offset * int((l[0] - 1) / (point_width)) + shape.append([x, y, blank]) + debug2("=====") + debug2(f"id: {l[0]}\tx: {x}\ty: {y}\t\tpoint_width: {point_width}\t\n") + + for p in l: + x = point_offset * ((p - 1) % (point_width)) + y = point_offset * int((p - 1) / (point_width)) + shape.append([x, y, white]) + debug2(f"id: {p}\tx: {x}\ty: {y}\t\tpoint_width: {point_width}\t\n") + +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)) + diff --git a/libs3/plotOptimizer.py b/libs3/plotOptimizer.py new file mode 100644 index 0000000..3c6eadc --- /dev/null +++ b/libs3/plotOptimizer.py @@ -0,0 +1,93 @@ +class Node: + def __init__(self, sid, color): + self.sid = sid + self.connected = [] + self.used = False + self.color = color + self.is_free = None # may be an other value to initialise + + def add_nodes(self, neighbord): + not_the_same = neighbord != self.sid + not_allrady_inside = neighbord not in self.connected + + if neighbord != self.sid and neighbord not in self.connected: + self.connected.append(neighbord) + + # print the content of the objet to debug with print() + def __repr__(self): + is_free = " \t###" if self.is_free else " \t___" + return is_free + str(self.connected) + "\n" + +#class Graph: +# nodes = {} # dict of all nodes +# +# def __init__(selt): +# pass + +def list_to_nodes(pl): + all_nodes = {} # it will contain all nodes + sid_prev = None + + for p in pl: + sid = str([int(p[0]), int(p[1])]) + is_colored = p[2] != 0 + + if is_colored: + if sid not in all_nodes: + all_nodes[sid] = Node(sid, p[2]) + if sid_prev != None: + all_nodes[sid].add_nodes(sid_prev) + all_nodes[sid_prev].add_nodes(sid) + sid_prev = sid if is_colored else None + return all_nodes + +# recursiv function witch get all connected node for one component and tag them as used +def get_one_comp(id_elem, nodes): + comp = [] + + comp.append(id_elem) + nodes[id_elem].used = True + for id_near in nodes[id_elem].connected: + if nodes[id_near].used == False: + comp += get_one_comp(id_near, nodes) + return comp + +def get_comps(nodes): + comps = [] #all component + iter_nodes = iter(nodes) + nb_elem = len(nodes) + + for id_nodes in iter_nodes: + if nodes[id_nodes].used == False: + comps.append(get_one_comp(id_nodes, nodes)) + return comps + +# if ther is a class for the component it would be a good idea to set en atribute about eulerian graph or non eulerian graph +def set_free_vertices(components, nodes): + for comp in components: + all_even_neighbord = True + for id_node in comp: + if len(nodes[id_node].connected) % 2 == 0: # test if even neighbord + nodes[id_node].is_free = False + else: + nodes[id_node].is_free = True + all_even_neighbord = False + if all_even_neighbord: + for id_node in comp: + nodes[id_node].is_free = True + +def optimizer(pl): + all_nodes = {} # it will contain all nodes + components = [] # list of connected node as a graph + + # construct dict of connected all_nodes + all_nodes = list_to_nodes(pl) + components = get_comps(all_nodes) + set_free_vertices(components, all_nodes) + print("\n\nall_nodes:\n", all_nodes) + print("\n\nconnected_components:\n", components) + return pl + +if __name__ == '__main__': + pl = [(355, 262, 0), (355, 262, 16777215), (300, 130, 16777215), (432, 75, 16777215), (487, 207, 16777215), (355, 262, 16777215), (355, 262, 0), (0, 435, 0), (0, 480, 16777215), (0, 300, 16777215), (135, 300, 16777215), (135, 570, 16777215), (135, 570, 16777215), (135, 300, 16777215), (135, 300, 0), (135, 300, 16777215), (225, 480, 16777215), (225, 480, 0), (510, 450, 0), (510, 450, 16777215), (600, 420, 16777215), (600, 300, 16777215), (720, 300, 16777215), (720, 420, 16777215), (810, 450, 16777215), (810, 450, 0)] + optimizer(pl) diff --git a/libs3/tracer3.py b/libs3/tracer3.py index 59a4800..48a12d9 100644 --- a/libs3/tracer3.py +++ b/libs3/tracer3.py @@ -81,7 +81,8 @@ import pdb import ast import redis -from libs3 import homographyp +from libs3 import homographyp, plotOptimizer as po + import numpy as np import binascii @@ -223,43 +224,39 @@ class DAC(object): while True: - #pdb.set_trace() + self.pl = po.optimizer(self.pl) for indexpoint,currentpoint in enumerate(self.pl): - #print indexpoint, currentpoint + + # transformations des point au format adapter au etherdream xyc = [currentpoint[0],currentpoint[1],currentpoint[2]] self.xyrgb = self.EtherPoint(xyc) - #print(self.xyrgb[2:]) rgb = (round(self.xyrgb[2:][0] *self.intred/100), round(self.xyrgb[2:][1] *self.intgreen/100), round(self.xyrgb[2:][2] *self.intblue/100)) - #print("rgb :", rgb) - #round(*self.intred/100) - #round(*self.intgreen/100) - #round(*self.intblue/100) - - delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1] - - #test adaptation selon longueur ligne - if math.hypot(delta_x, delta_y) < 4000: + yield self.xyrgb + ##**//# ajout de point pour un tracer adapter + ##**//delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1] + ##**//#test adaptation selon longueur ligne + ##**//if math.hypot(delta_x, delta_y) < 4000: - # For glitch art : decrease lsteps - #l_steps = [ (1.0, 8)] - l_steps = gstt.stepshortline + ##**// # For glitch art : decrease lsteps + ##**// #l_steps = [ (1.0, 8)] + ##**// l_steps = gstt.stepshortline - else: - # For glitch art : decrease lsteps - #l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)] - l_steps = gstt.stepslongline + ##**//else: + ##**// # For glitch art : decrease lsteps + ##**// #l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)] + ##**// l_steps = gstt.stepslongline - for e in l_steps: - step = e[0] + ##**//for e in l_steps: + ##**// step = e[0] - for i in range(0,e[1]): + ##**// for i in range(0,e[1]): - self.xyrgb_step = (self.xyrgb_prev[0] + step*delta_x, self.xyrgb_prev[1] + step*delta_y) + rgb # + self.xyrgb_prev[2:]# + rgb - #print(self.xyrgb_step) - yield self.xyrgb_step + ##**// self.xyrgb_step = (self.xyrgb_prev[0] + step*delta_x, self.xyrgb_prev[1] + step*delta_y) + rgb # + self.xyrgb_prev[2:]# + rgb + ##**// #print(self.xyrgb_step) + ##**// yield self.xyrgb_step - self.xyrgb_prev = self.xyrgb + ##**//self.xyrgb_prev = self.xyrgb def GetPoints(self, n): From 6994ea911fde8de313a2229b0a738bd9604b2ba0 Mon Sep 17 00:00:00 2001 From: Lapin Date: Wed, 30 Dec 2020 19:11:29 +0100 Subject: [PATCH 3/4] [fix]: drawing optimization fix the adjust_brightness() function. blank point was not included --- libs3/plotOptimizer.py | 330 ++++++++++++++++++++++++++++++----------- 1 file changed, 246 insertions(+), 84 deletions(-) diff --git a/libs3/plotOptimizer.py b/libs3/plotOptimizer.py index 3c6eadc..903e0fb 100644 --- a/libs3/plotOptimizer.py +++ b/libs3/plotOptimizer.py @@ -1,93 +1,255 @@ -class Node: - def __init__(self, sid, color): - self.sid = sid - self.connected = [] - self.used = False - self.color = color - self.is_free = None # may be an other value to initialise +import math + +# parameter for angles +pps = 25000 +time_us_angle_zero = float(400) # it's just a random value, it must be tested (us = micro second) +time_us_per_point = float(1000000 / pps) # 40 us for 25kpps (us = micro second) + +# parmeter for brightness +max_lengh = 50 # in pixel, random value as well + +import sys +def debug(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + +def different_position(p1, p2): + return (int(p2[0]) != int(p1[0])) or (int(p2[1]) != int(p1[1])) + +def sub(p1, p2): + return [] + +def no_blanks_points(*points): + for p in points: + if p[2] == 0: + return False + return True + +def angle_exist(p1, p2, p3): + return no_blanks_points(p1, p2, p3) and different_position(p1, p2) and different_position(p2, p3) + +def scalar_product(v1, v2): + return v1[0] * v2[0] + v1[1] * v2[1] + +def length(v): + return math.sqrt(scalar_product(v, v)) + +def normalize(v): + l = length(v) + return [v[0] / l, v[1] / l] + +def sub(p1, p2): + return [p1[0] - p2[0], p1[1] - p2[1]] + +def add(p1, p2): + return [p1[0] + p2[0], p1[1] + p2[1]] + +def mult_by_scalar(p, scalar): + return [p[0] * scalar, p[1] * scalar] + +# 90 deg rotate to the right of v1 when y axes is directed to the floor +def rot_90_right(v): + return [-v[1], v[0]] + +def get_angle_degree(p1, p2, p3): + v1 = sub(p2, p1) + v2 = sub(p2, p3) + d1x = normalize(v1) + d1y = rot_90_right(d1x) + x = scalar_product(d1x, v2) + y = scalar_product(d1y, v2) + angle = 180 - abs(math.degrees(math.atan2(y, x))) + return angle - def add_nodes(self, neighbord): - not_the_same = neighbord != self.sid - not_allrady_inside = neighbord not in self.connected +def point_to_add(angle): + return int(float((1 - (angle / 180.0)) * time_us_angle_zero) / time_us_per_point) - if neighbord != self.sid and neighbord not in self.connected: - self.connected.append(neighbord) +def adjusts_angles(pl): + if len(pl) < 3: + return pl - # print the content of the objet to debug with print() - def __repr__(self): - is_free = " \t###" if self.is_free else " \t___" - return is_free + str(self.connected) + "\n" + new_pl = [] + previous = pl[0] + middle = pl[1] + new_pl.append(pl[0]) + for ensuing in pl[2:]: + if angle_exist(previous, middle, ensuing): + angle = get_angle_degree(previous, middle, ensuing) + nb_point_added = point_to_add(angle) + for i in range(nb_point_added): + new_pl.append(middle) + new_pl.append(middle) + previous = middle + middle = ensuing + new_pl.append(pl[-1]) + return new_pl + +def adjusts_brightness(pl): + new_pl = [] + + if len(pl) < 1: + return pl + new_pl.append(pl[0]) + prev = pl[0] + for current in pl[1:]: + new_pl.append(prev) + if no_blanks_points(prev, current): + diff = sub(current, prev) + l = length(diff) + if l > max_lengh: + nb_add = math.ceil(l / max_lengh) + print("\n\n===") + print("from:", prev) + print("to:", current) + print("diff:", diff) + for i in range(nb_add): + factor = float(i) / float(nb_add) + print("factor:", factor) + new_point = add(prev, mult_by_scalar(diff, factor)) + [prev[2]] + print(new_point) + new_pl.append(new_point) + #else: + # new_pl.append() + prev = current + new_pl.append(pl[-1]) + + return new_pl + +def adjust_ending_point(pl): + # si il y a trop de point noir, on en enleve + # si il y a un que 1 point noir: + # on en met un autre + return pl + +def optimizer(pl): + initial_length = len(pl) + + pl = adjusts_angles(pl) + added_by_angle = len(pl) - initial_length + + pl = adjusts_brightness(pl) + added_by_brightness = len(pl) - (added_by_angle + initial_length) + + #points_added = added_by_angle + added_by_brightness + #print("\n\ninital_lenght:", initial_length, "\tadded by angles:", added_by_angle, "\tadded by brightness:", added_by_brightness ) + return pl + +if __name__ == '__main__': + # The 3 pl_somthing are used to test and debug the algorythm without + # using all the programe archithecture. The goal is to be able to execute + # the code snippet without errors being caught by LJ. + pl_component = [(355, 262, 0), (355, 262, 16777215), (300, 130, 16777215), (432, 75, 16777215), (487, 207, 16777215), (355, 262, 16777215), (355, 262, 0), (0, 435, 0), (0, 480, 16777215), (0, 300, 16777215), (135, 300, 16777215), (135, 570, 16777215), (135, 570, 16777215), (135, 300, 16777215), (135, 300, 0), (135, 300, 16777215), (225, 480, 16777215), (225, 480, 0), (510, 450, 0), (510, 450, 16777215), (600, 420, 16777215), (600, 300, 16777215), (720, 300, 16777215), (720, 420, 16777215), (810, 450, 16777215), (810, 450, 0)] + + pl_brightness = [[50, 50, 0], [50, 50, 16777215], [50, 750, 16777215], [750, 750, 16777215], [750, 50, 16777215], [50, 50, 16777215], [50, 50, 0], [100, 100, 0], [100, 100, 16777215], [100, 700, 16777215], [700, 700, 16777215], [700, 100, 16777215], [100, 100, 16777215], [100, 100, 0], [150, 150, 0], [150, 150, 16777215], [150, 650, 16777215], [650, 650, 16777215], [650, 150, 16777215], [150, 150, 16777215], [150, 150, 0], [200, 200, 0], [200, 200, 16777215], [200, 600, 16777215], [600, 600, 16777215], [600, 200, 16777215], [200, 200, 16777215], [200, 200, 0], [250, 250, 0], [250, 250, 16777215], [250, 550, 16777215], [550, 550, 16777215], [550, 250, 16777215], [250, 250, 16777215], [250, 250, 0], [300, 300, 0], [300, 300, 16777215], [300, 500, 16777215], [500, 500, 16777215], [500, 300, 16777215], [300, 300, 16777215], [300, 300, 0], [350, 350, 0], [350, 350, 16777215], [350, 450, 16777215], [450, 450, 16777215], [450, 350, 16777215], [350, 350, 16777215], [350, 350, 0]] + pl_angle = [[10.0, 83.0, 0], [10.0, 83.0, 16777215], [85, 83, 16777215], [160.0, 83.0, 16777215], [160.0, 83.0, 0], [160.0, 87.0, 0], [160.0, 87.0, 16777215], [85, 87, 16777215], [10.0, 87.0, 16777215], [10.0, 87.0, 0], [170.2853976431191, 76.46331929392564, 0], [170.2853976431191, 76.46331929392564, 16777215], [245, 83, 16777215], [319.7146023568809, 76.46331929392564, 16777215], [319.7146023568809, 76.46331929392564, 0], [319.7146023568809, 93.53668070607436, 0], [319.7146023568809, 93.53668070607436, 16777215], [245, 87, 16777215], [170.2853976431191, 93.53668070607436, 16777215], [170.2853976431191, 93.53668070607436, 0], [331.1394185240844, 69.97638667498022, 0], [331.1394185240844, 69.97638667498022, 16777215], [405, 83, 16777215], [478.8605814759156, 69.97638667498022, 16777215], [478.8605814759156, 69.97638667498022, 0], [478.8605814759156, 100.02361332501978, 0], [478.8605814759156, 100.02361332501978, 16777215], [405, 87, 16777215], [331.1394185240844, 100.02361332501978, 16777215], [331.1394185240844, 100.02361332501978, 0], [492.55556302831985, 63.58857161731095, 0], [492.55556302831985, 63.58857161731095, 16777215], [565, 83, 16777215], [637.4444369716801, 63.58857161731095, 16777215], [637.4444369716801, 63.58857161731095, 0], [637.4444369716801, 106.41142838268905, 0], [637.4444369716801, 106.41142838268905, 16777215], [565, 87, 16777215], [492.55556302831985, 106.41142838268905, 16777215], [492.55556302831985, 106.41142838268905, 0], [14.523053441056874, 217.34848925057486, 0], [14.523053441056874, 217.34848925057486, 16777215], [85, 243, 16777215], [155.47694655894313, 217.34848925057486, 16777215], [155.47694655894313, 217.34848925057486, 0], [155.47694655894313, 272.65151074942514, 0], [155.47694655894313, 272.65151074942514, 16777215], [85, 247, 16777215], [14.523053441056874, 272.65151074942514, 16777215], [14.523053441056874, 272.65151074942514, 0], [177.02691597225126, 211.30363036944755, 0], [177.02691597225126, 211.30363036944755, 16777215], [245, 243, 16777215], [312.97308402774877, 211.30363036944755, 16777215], [312.97308402774877, 211.30363036944755, 0], [312.97308402774877, 278.69636963055245, 0], [312.97308402774877, 278.69636963055245, 16777215], [245, 247, 16777215], [177.02691597225126, 278.69636963055245, 16777215], [177.02691597225126, 278.69636963055245, 0], [340.0480947161671, 205.5, 0], [340.0480947161671, 205.5, 16777215], [405, 243, 16777215], [469.9519052838329, 205.5, 16777215], [469.9519052838329, 205.5, 0], [469.9519052838329, 284.5, 0], [469.9519052838329, 284.5, 16777215], [405, 247, 16777215], [340.0480947161671, 284.5, 16777215], [340.0480947161671, 284.5, 0], [503.5635966783256, 199.98176727367155, 0], [503.5635966783256, 199.98176727367155, 16777215], [565, 243, 16777215], [626.4364033216743, 199.98176727367155, 16777215], [626.4364033216743, 199.98176727367155, 0], [626.4364033216743, 290.01823272632845, 0], [626.4364033216743, 290.01823272632845, 16777215], [565, 247, 16777215], [503.5635966783256, 290.01823272632845, 16777215], [503.5635966783256, 290.01823272632845, 0], [27.546666766076648, 354.79092927350956, 0], [27.546666766076648, 354.79092927350956, 16777215], [85, 403, 16777215], [142.45333323392336, 354.79092927350956, 16777215], [142.45333323392336, 354.79092927350956, 0], [142.45333323392336, 455.20907072649044, 0], [142.45333323392336, 455.20907072649044, 16777215], [85, 407, 16777215], [27.546666766076648, 455.20907072649044, 16777215], [27.546666766076648, 455.20907072649044, 0], [191.96699141100893, 349.96699141100896, 0], [191.96699141100893, 349.96699141100896, 16777215], [245, 403, 16777215], [298.03300858899104, 349.96699141100896, 16777215], [298.03300858899104, 349.96699141100896, 0], [298.03300858899104, 460.03300858899104, 0], [298.03300858899104, 460.03300858899104, 16777215], [245, 407, 16777215], [191.96699141100893, 460.03300858899104, 16777215], [191.96699141100893, 460.03300858899104, 0], [356.79092927350956, 345.54666676607667, 0], [356.79092927350956, 345.54666676607667, 16777215], [405, 403, 16777215], [453.20907072649044, 345.54666676607667, 16777215], [453.20907072649044, 345.54666676607667, 0], [453.20907072649044, 464.45333323392333, 0], [453.20907072649044, 464.45333323392333, 16777215], [405, 407, 16777215], [356.79092927350956, 464.45333323392333, 16777215], [356.79092927350956, 464.45333323392333, 0], [521.9817672736715, 341.5635966783256, 0], [521.9817672736715, 341.5635966783256, 16777215], [565, 403, 16777215], [608.0182327263285, 341.5635966783256, 16777215], [608.0182327263285, 341.5635966783256, 0], [608.0182327263285, 468.4364033216744, 0], [608.0182327263285, 468.4364033216744, 16777215], [565, 407, 16777215], [521.9817672736715, 468.4364033216744, 16777215], [521.9817672736715, 468.4364033216744, 0], [47.49999999999999, 498.0480947161671, 0], [47.49999999999999, 498.0480947161671, 16777215], [85, 563, 16777215], [122.5, 498.0480947161671, 16777215], [122.5, 498.0480947161671, 0], [122.5, 631.951905283833, 0], [122.5, 631.951905283833, 16777215], [85, 567, 16777215], [47.49999999999999, 631.951905283833, 16777215], [47.49999999999999, 631.951905283833, 0], [213.30363036944755, 495.02691597225123, 0], [213.30363036944755, 495.02691597225123, 16777215], [245, 563, 16777215], [276.69636963055245, 495.02691597225123, 16777215], [276.69636963055245, 495.02691597225123, 0], [276.69636963055245, 634.9730840277488, 0], [276.69636963055245, 634.9730840277488, 16777215], [245, 567, 16777215], [213.30363036944755, 634.9730840277488, 16777215], [213.30363036944755, 634.9730840277488, 0], [379.34848925057486, 492.52305344105685, 0], [379.34848925057486, 492.52305344105685, 16777215], [405, 563, 16777215], [430.65151074942514, 492.52305344105685, 16777215], [430.65151074942514, 492.52305344105685, 0], [430.65151074942514, 637.4769465589432, 0], [430.65151074942514, 637.4769465589432, 16777215], [405, 567, 16777215], [379.34848925057486, 637.4769465589432, 16777215], [379.34848925057486, 637.4769465589432, 0], [545.5885716173109, 490.55556302831985, 0], [545.5885716173109, 490.55556302831985, 16777215], [565, 563, 16777215], [584.4114283826891, 490.55556302831985, 16777215], [584.4114283826891, 490.55556302831985, 0], [584.4114283826891, 639.4444369716801, 0], [584.4114283826891, 639.4444369716801, 16777215], [565, 567, 16777215], [545.5885716173109, 639.4444369716801, 16777215], [545.5885716173109, 639.4444369716801, 0], [71.97638667498022, 649.1394185240844, 0], [71.97638667498022, 649.1394185240844, 16777215], [85, 723, 16777215], [98.02361332501978, 649.1394185240844, 16777215], [98.02361332501978, 649.1394185240844, 0], [98.02361332501978, 800.8605814759156, 0], [98.02361332501978, 800.8605814759156, 16777215], [85, 727, 16777215], [71.97638667498022, 800.8605814759156, 16777215], [71.97638667498022, 800.8605814759156, 0], [238.46331929392565, 648.285397643119, 0], [238.46331929392565, 648.285397643119, 16777215], [245, 723, 16777215], [251.53668070607435, 648.285397643119, 16777215], [251.53668070607435, 648.285397643119, 0], [251.53668070607435, 801.714602356881, 0], [251.53668070607435, 801.714602356881, 16777215], [245, 727, 16777215], [238.46331929392565, 801.714602356881, 16777215], [238.46331929392565, 801.714602356881, 0], [405.0, 648.0, 0], [405.0, 648.0, 16777215], [405, 723, 16777215], [405.0, 648.0, 16777215], [405.0, 648.0, 0], [405.0, 802.0, 0], [405.0, 802.0, 16777215], [405, 727, 16777215], [405.0, 802.0, 16777215], [405.0, 802.0, 0]] + + optimizer(pl_brightness) + + +###########################################################################3333 +# | Not used yet, it's for the eulerian graph optimization, probably comming soon =) +# v +# +#class Node: +# def __init__(self, sid, color): +# self.sid = sid +# self.connected = [] +# self.used = False +# self.color = color +# self.is_free = None # may be an other value to initialise +# self.blank_connection = "" +# +# def add_nodes(self, neighbord): +# not_the_same = neighbord != self.sid +# not_allrady_inside = neighbord not in self.connected +# +# if neighbord != self.sid and neighbord not in self.connected: +# self.connected.append(neighbord) +# +# # print the content of the objet to debug with print() +# def __repr__(self): +# is_free = " \t###" if self.is_free else " \t___" +# return is_free + str(self.connected) + "\n" +# +#class Component: +# def __init__(self, all_nodes, comp_nodes): +# self.all_nodes = all_nodes +# self.id_nodes = comp_nodes +# self.id_free_nodes = [] +# self.is_eulerian_circuit = True +# # centre x,y +# # bounding box +# # other +# pass +# #class Graph: # nodes = {} # dict of all nodes # # def __init__(selt): # pass - -def list_to_nodes(pl): - all_nodes = {} # it will contain all nodes - sid_prev = None - - for p in pl: - sid = str([int(p[0]), int(p[1])]) - is_colored = p[2] != 0 - - if is_colored: - if sid not in all_nodes: - all_nodes[sid] = Node(sid, p[2]) - if sid_prev != None: - all_nodes[sid].add_nodes(sid_prev) - all_nodes[sid_prev].add_nodes(sid) - sid_prev = sid if is_colored else None - return all_nodes - -# recursiv function witch get all connected node for one component and tag them as used -def get_one_comp(id_elem, nodes): - comp = [] - - comp.append(id_elem) - nodes[id_elem].used = True - for id_near in nodes[id_elem].connected: - if nodes[id_near].used == False: - comp += get_one_comp(id_near, nodes) - return comp - -def get_comps(nodes): - comps = [] #all component - iter_nodes = iter(nodes) - nb_elem = len(nodes) - - for id_nodes in iter_nodes: - if nodes[id_nodes].used == False: - comps.append(get_one_comp(id_nodes, nodes)) - return comps - -# if ther is a class for the component it would be a good idea to set en atribute about eulerian graph or non eulerian graph -def set_free_vertices(components, nodes): - for comp in components: - all_even_neighbord = True - for id_node in comp: - if len(nodes[id_node].connected) % 2 == 0: # test if even neighbord - nodes[id_node].is_free = False - else: - nodes[id_node].is_free = True - all_even_neighbord = False - if all_even_neighbord: - for id_node in comp: - nodes[id_node].is_free = True - -def optimizer(pl): - all_nodes = {} # it will contain all nodes - components = [] # list of connected node as a graph - - # construct dict of connected all_nodes - all_nodes = list_to_nodes(pl) - components = get_comps(all_nodes) - set_free_vertices(components, all_nodes) - print("\n\nall_nodes:\n", all_nodes) - print("\n\nconnected_components:\n", components) - return pl - -if __name__ == '__main__': - pl = [(355, 262, 0), (355, 262, 16777215), (300, 130, 16777215), (432, 75, 16777215), (487, 207, 16777215), (355, 262, 16777215), (355, 262, 0), (0, 435, 0), (0, 480, 16777215), (0, 300, 16777215), (135, 300, 16777215), (135, 570, 16777215), (135, 570, 16777215), (135, 300, 16777215), (135, 300, 0), (135, 300, 16777215), (225, 480, 16777215), (225, 480, 0), (510, 450, 0), (510, 450, 16777215), (600, 420, 16777215), (600, 300, 16777215), (720, 300, 16777215), (720, 420, 16777215), (810, 450, 16777215), (810, 450, 0)] - optimizer(pl) +# +#def list_to_nodes(pl): +# all_nodes = {} # it will contain all nodes +# sid_prev = None +# +# for p in pl: +# sid = str([int(p[0]), int(p[1])]) +# is_colored = p[2] != 0 +# +# if is_colored: +# if sid not in all_nodes: +# all_nodes[sid] = Node(sid, p[2]) +# if sid_prev != None: +# all_nodes[sid].add_nodes(sid_prev) +# all_nodes[sid_prev].add_nodes(sid) +# sid_prev = sid if is_colored else None +# return all_nodes +# +## recursiv function witch get all connected node for one component and tag them as used +#def get_one_comp(id_elem, nodes): +# comp = [] +# +# comp.append(id_elem) +# nodes[id_elem].used = True +# for id_near in nodes[id_elem].connected: +# if nodes[id_near].used == False: +# comp += get_one_comp(id_near, nodes) +# return comp +# +#def get_comps(nodes): +# comps = [] #all component +# iter_nodes = iter(nodes) +# nb_elem = len(nodes) +# +# for id_nodes in iter_nodes: +# if nodes[id_nodes].used == False: +# comps.append(get_one_comp(id_nodes, nodes)) +# return comps +# +## if ther is a class for the component it would be a good idea to set en atribute about eulerian graph or non eulerian graph +#def set_free_vertices(components, nodes): +# for comp in components: +# all_even_neighbord = True +# for id_node in comp: +# if len(nodes[id_node].connected) % 2 == 0: # test if even neighbord +# nodes[id_node].is_free = False +# else: +# nodes[id_node].is_free = True +# all_even_neighbord = False +# if all_even_neighbord: +# for id_node in comp: +# nodes[id_node].is_free = True +# +#def optimizer_old(pl): +# all_nodes = {} # it will contain all nodes +# components = [] # list of connected node as a graph +# +# # construct dict of connected all_nodes +# all_nodes = list_to_nodes(pl) +# components = get_comps(all_nodes) +# set_free_vertices(components, all_nodes) +##@ print("\n\nall_nodes:\n", all_nodes) +##@ print("\n\nconnected_components:\n", components) +# return pl +# From 9fecb97df735162e44aee696707f72f2f2f3e9b1 Mon Sep 17 00:00:00 2001 From: Lapin Date: Wed, 30 Dec 2020 19:16:18 +0100 Subject: [PATCH 4/4] [feat] drawing optimisation add some generator to test the optoimisation: adjust_brightness.py: set some rectangle to rerify the consant of brightnes keyborad_input.py: is an exenmple of non blocking input reading angleInteractive.py: is an interactiv version to test the angle. you can separatly set the lenght of each segment you can set the angle it must be run without brightnes optimization because mey be lenght have an importance --- .../drawingTests/adjust_brightness.py | 73 +++++ .../drawingTests/angleInteractive.py | 262 ++++++++++++++++++ .../generators/drawingTests/keyborad_input.py | 77 +++++ 3 files changed, 412 insertions(+) create mode 100644 clitools/generators/drawingTests/adjust_brightness.py create mode 100644 clitools/generators/drawingTests/angleInteractive.py create mode 100644 clitools/generators/drawingTests/keyborad_input.py diff --git a/clitools/generators/drawingTests/adjust_brightness.py b/clitools/generators/drawingTests/adjust_brightness.py new file mode 100644 index 0000000..060be26 --- /dev/null +++ b/clitools/generators/drawingTests/adjust_brightness.py @@ -0,0 +1,73 @@ + +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +This generator print different squar from big to small. +The purepose is to see the difference of brightness with the length + +v0.1.0 + +LICENCE : CC + +by lapin (aka nipal) + +''' + +from __future__ import print_function +import time +import argparse +import sys +import math + +name="generator::endingPoint" + + +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)) + +width = 800 +height = 800 +offset = 50 + +white = 0xFFFFFF +blank = 0x0 + +shape = [] + +def set_shape(): + nb_spire = int(width / (2 * offset)) - 1 + for i in range(1, nb_spire + 1): + shape.append([ i * offset, i * offset, blank]) + shape.append([ i * offset, i * offset, white]) + shape.append([ i * offset, height - i * offset, white]) + shape.append([width - i * offset, height - i * offset, white]) + shape.append([width - i * offset, i * offset, white]) + shape.append([ i * offset, i * offset, white]) + shape.append([ i * offset, i * offset, blank]) + +set_shape() + +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)) diff --git a/clitools/generators/drawingTests/angleInteractive.py b/clitools/generators/drawingTests/angleInteractive.py new file mode 100644 index 0000000..3fa8e30 --- /dev/null +++ b/clitools/generators/drawingTests/angleInteractive.py @@ -0,0 +1,262 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +This generator print diferent one angle but you can modify it interactively. +The key are: + * '' => *somthing* + * ... + +v0.1.0 + +LICENCE : CC + +by lapin (aka nipal) + +''' + +from __future__ import print_function +import time +import argparse +import math +import sys +# import for non-bloking input reading +#import sys +import select +import tty +import termios + +name="generator::endingPoint" + +def debug(*args, **kwargs): + if( verbose == False ): + return + print(*args, file=sys.stderr, **kwargs) + +def isData(): + return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []) + +def flush_input(): + try: + import msvcrt + while msvcrt.kbhit(): + msvcrt.getch() + except ImportError: + import sys, termios #for linux/unix + termios.tcflush(sys.stdin, termios.TCIOFLUSH) + +old_settings = termios.tcgetattr(sys.stdin) + + +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)) + +width = 800 +height = 800 + +white = 0xFFFFFF +blank = 0x0 + +seg1_length = 100 +seg2_length = 100 +ang = 50 + +incrLengthLittle= 5 +incrLengthLot= 20 +incrAngleLittle= 1 +incrAngleLot= 10 +angle_min = 0 +angle_max = 90 +length_min = 1 +length_max = 350 + +shape = [] + +# angle +def ang_add_1(): + global ang + + if ang + incrAngleLittle <= angle_max: + ang += incrAngleLittle + else: + ang = angle_max + +def ang_add_2(): + global ang + + if ang + incrAngleLot <= angle_max: + ang += incrAngleLot + else: + ang = angle_max + +def ang_sub_1(): + global ang + + if ang - incrAngleLittle >= angle_min: + ang -= incrAngleLittle + else: + ang = angle_min + +def ang_sub_2(): + global ang + + if ang - incrAngleLot >= angle_min: + ang -= incrAngleLot + else: + ang = angle_min + +# seg1 +def seg_1_add_1(): + global seg1_length + + if seg1_length + incrLengthLittle <= length_max: + seg1_length += incrLengthLittle + else: + seg1_length = length_max + +def seg_1_add_2(): + global seg1_length + + if seg1_length + incrLengthLot <= length_max: + seg1_length += incrLengthLot + else: + seg1_length = length_max + +def seg_1_sub_1(): + global seg1_length + + if seg1_length - incrLengthLittle >= length_min: + seg1_length -= incrLengthLittle + else: + seg1_length = length_min + +def seg_1_sub_2(): + global seg1_length + + if seg1_length - incrLengthLot >= length_min: + seg1_length -= incrLengthLot + else: + seg1_length = length_min + +# seg2 +def seg_2_add_1(): + global seg2_length + + if seg2_length + incrLengthLittle <= length_max: + seg2_length += incrLengthLittle + else: + seg2_length = length_max + +def seg_2_add_2(): + global seg2_length + + if seg2_length + incrLengthLot <= length_max: + seg2_length += incrLengthLot + else: + seg2_length = length_max + +def seg_2_sub_1(): + global seg2_length + + if seg2_length - incrLengthLittle >= length_min: + seg2_length -= incrLengthLittle + else: + seg2_length = length_min + +def seg_2_sub_2(): + global seg2_length + + if seg2_length - incrLengthLot >= length_min: + seg2_length -= incrLengthLot + else: + seg2_length = length_min + +action = { + # segment 1 + 'q': seg_1_sub_1, + 'w': ssg_1_add_1, + 'a': seg_1_sub_2, + 's': seg_1_add_2, + + # segment 2 + 'o': seg_2_sub_1, + 'p': seg_2_add_1, + 'l': seg_2_sub_2, + ';': seg_2_add_2, + + # angle + 't': ang_sub_1, + 'y': ang_add_1, + 'g': ang_sub_2, + 'h': ang_add_2, + } + +def print_param(): + debug("\n\n===") + debug("segment 1 length:", seg1_length) + debug("segment 2 length:", seg2_length) + debug("angle:", ang) + +def set_shape(): + global shape + shape.clear() + + cx = width / 2 + cy = height / 2 + + px1 = int(seg1_length * math.cos(math.radians(ang))) + py1 = int(seg1_length * math.sin(math.radians(ang))) + px2 = int(seg2_length * math.cos(math.radians(ang))) + py2 = int(seg2_length * math.sin(math.radians(ang))) + + # line up + shape.append([-px1 + cx, -py1 + cy, blank]) + shape.append([-px1 + cx, -py1 + cy, white]) + shape.append([ cx, + cy, white]) + shape.append([ px2 + cx, -py2 + cy, white]) + shape.append([ px2 + cx, -py2 + cy, blank]) + + # line down + shape.append([ px1 + cx, py1 + cy, blank]) + shape.append([ px1 + cx, py1 + cy, white]) + shape.append([ cx, + cy, white]) + shape.append([-px2 + cx, py2 + cy, white]) + shape.append([-px2 + cx, py2 + cy, blank]) + +def update_param(c): + if c in action: + action[c]() + print_param() + set_shape() + +try: + tty.setcbreak(sys.stdin.fileno()) + + set_shape() + print_param() + print(shape, flush=True); + while 1: + if isData(): + c = sys.stdin.read(1) + update_param(c) + + 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)) + +finally: + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) diff --git a/clitools/generators/drawingTests/keyborad_input.py b/clitools/generators/drawingTests/keyborad_input.py new file mode 100644 index 0000000..88a357d --- /dev/null +++ b/clitools/generators/drawingTests/keyborad_input.py @@ -0,0 +1,77 @@ +# code exemple find at : https://stackoverflow.com/questions/2408560/python-nonblocking-console-input + +import sys +import select +import tty +import termios + +def isData(): + return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []) + +old_settings = termios.tcgetattr(sys.stdin) + +try: + tty.setcbreak(sys.stdin.fileno()) + + i = 0 + while 1: + #if i % 100000 == 0: + # print("i", i) + #i += 1 + if isData(): + c = sys.stdin.read(1) + print(c) + if c == '\x1b': # x1b is ESC + break + +finally: + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) + + + +### for windows +#import msvcrt +# +#num = 0 +#done = False +#while not done: +# print(num) +# num += 1 +# +# if msvcrt.kbhit(): +# print "you pressed",msvcrt.getch(),"so now i will quit" +# done = True +# + +## cross platforme (but may be a bit huge to import pygame...) +#import pygame +#from pygame.locals import * +# +#def display(str): +# text = font.render(str, True, (255, 255, 255), (159, 182, 205)) +# textRect = text.get_rect() +# textRect.centerx = screen.get_rect().centerx +# textRect.centery = screen.get_rect().centery +# +# screen.blit(text, textRect) +# pygame.display.update() +# +#pygame.init() +#screen = pygame.display.set_mode( (640,480) ) +#pygame.display.set_caption('Python numbers') +#screen.fill((159, 182, 205)) +# +#font = pygame.font.Font(None, 17) +# +#num = 0 +#done = False +#while not done: +# display( str(num) ) +# num += 1 +# +# pygame.event.pump() +# keys = pygame.key.get_pressed() +# if keys[K_ESCAPE]: +# done = True +# +