Last active
December 19, 2020 15:48
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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