Skip to content

Instantly share code, notes, and snippets.

@el3
Last active December 19, 2020 15:48
Show Gist options
  • Save el3/8dd6603b194eb37c22b8cafa8e5bb83a to your computer and use it in GitHub Desktop.
Save el3/8dd6603b194eb37c22b8cafa8e5bb83a to your computer and use it in GitHub Desktop.
A kivy example, that will take touch inputs as input, and will fit a function to the points, and draw a line. With slider to test higher orders. And textinputs, where you can use arrow up and down to adjust numbers
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.graphics import Line, Ellipse, Color
from kivy.properties import ListProperty, StringProperty, NumericProperty
from kivy.core.window import Window
import numpy as np
KV = """
<MyViewclass@MyTextInput>:
index: 0
text: ""
multiline: False
on_text_validate:
self.rv.data[self.index]["text"] = self.text
self.mw._calc_points([float(i["text"]) for i in self.rv.data])
FloatLayout:
MyWidget:
id: mw
on_d:
rv.data = [{"text":str(value), "rv":rv, "index":index, "mw":mw} for index,value in enumerate(self.d)]
BoxLayout:
size_hint: None, 1
width: 200
orientation: "vertical"
RecycleView:
id: rv
viewclass: 'MyViewclass'
data: []
RecycleBoxLayout:
orientation: "vertical"
default_size: self.parent.width, dp(36)
default_size_hint: None, None
size_hint_y: None
height: self.minimum_height
Button:
text: "Calculate"
size_hint_y: 0.2
on_release:
if len(mw.xpoints): mw.calc_points()
Button:
text: "Clear"
size_hint_y: 0.2
on_release:
mw.clear_points()
Slider:
min: 0
max: 50
step: 1
size_hint_y: None
height: 50
x: 200
y: 50
value: 2
id: slider
on_value:
mw.order = self.value
if len(mw.xpoints): mw.calc_points()
Label:
size_hint: None, None
size: 1000, 50
x: 200
text: mw.label
"""
class MyTextInput(TextInput):
def keyboard_on_key_down(self, window, keycode, text, modifiers):
super().keyboard_on_key_down(window, keycode, text, modifiers)
key = keycode[1]
if key in ["up", "down"]:
if key == "up":
self.text = str(float(self.text)+float(self.text)/(10*len(self.rv.data)))
if key == "down":
self.text = str(float(self.text)-float(self.text)/(10*len(self.rv.data)))
self.rv.data[self.index]["text"] = self.text
self.mw._calc_points([float(i["text"]) for i in self.rv.data])
class MyWidget(BoxLayout):
xpoints = []
ypoints = []
clear = False
label = StringProperty("")
order = NumericProperty(2)
maincolor = Color(rgba=[1,1,1,1])
d = ListProperty([])
def on_touch_down(self, touch):
self.xpoints.append(touch.pos[0])
self.ypoints.append(touch.pos[1])
self.canvas.add(Color(rgba=[1,0,0,1]))
self.canvas.add(Ellipse(pos=(touch.pos[0]-8, touch.pos[1]-8), size=(16,16)))
def calc_points(self):
d = np.polyfit(self.xpoints, self.ypoints, self.order)
self._calc_points(d)
def _calc_points(self, d):
self.d = d
p = np.poly1d(self.d)
self.label = str(p)
self.maincolor.rgba = [1,1,1,0.1]
self.maincolor = Color(rgba=[1,1,1,1])
self.canvas.add(self.maincolor)
self.mainline = Line(points=[], width=1.5)
self.mainline.points = [(i, p(i)) for i in range(int(min(self.xpoints)),int(max(self.xpoints))+10,10)]
self.canvas.add(self.mainline)
self.canvas.add(Color(rgba=[0,0,1,1]))
self.line = Line(points=[], dash_offset=10, dash_length=10, width=1)
self.line.points = [(i, p(i)) for i in range(int(max(self.xpoints))+10,int(max(self.xpoints))+500,10)]
self.canvas.add(self.line)
self.line = Line(points=[], dash_offset=10, dash_length=10, width=1)
self.line.points = [(i, p(i)) for i in range(int(min(self.xpoints))-500,int(min(self.xpoints))+10,10)]
self.canvas.add(self.line)
def clear_points(self):
self.xpoints = []
self.ypoints = []
self.label = ""
self.canvas.clear()
class MyApp(App):
def build(self):
return Builder.load_string(KV)
MyApp().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment