File size: 2,448 Bytes
0611560
9ec2516
0611560
 
 
 
6e1639c
0611560
 
 
 
6e1639c
0611560
9ec2516
0611560
9ec2516
bae4e7e
0611560
9ec2516
0611560
6e1639c
0611560
 
 
6e1639c
0611560
 
6e1639c
0611560
 
 
bae4e7e
6e1639c
 
9ec2516
 
 
 
6e1639c
 
9ec2516
 
6e1639c
 
9ec2516
 
 
6e1639c
bae4e7e
 
 
6e1639c
9ec2516
0611560
 
bae4e7e
6e1639c
 
9ec2516
 
c8eca0d
9ec2516
 
 
bae4e7e
6e1639c
 
 
0611560
 
 
 
6e1639c
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import streamlit as st
from typing import List, Tuple
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
from bokeh.events import Tap

# Constants
WIDTH, HEIGHT = 600, 600
ELASTICITY = 0.3
DAMPING = 0.7

# Create touch points
num_points = 20
touch_points: List[Tuple[float, float]] = [(x, y) for x in range(50, WIDTH-50, int((WIDTH-100)/(num_points-1))) for y in range(50, HEIGHT-50, int((HEIGHT-100)/(num_points-1)))]
original_points = touch_points.copy()
velocities: List[Tuple[float, float]] = [(0.0, 0.0)] * len(touch_points)
is_affected: List[bool] = [False] * len(touch_points)

source = ColumnDataSource(data=dict(x=[x for x, y in touch_points], y=[y for x, y in touch_points]))

# Set up the Bokeh plot
p = figure(width=WIDTH, height=HEIGHT, tools="", toolbar_location=None)
p.circle('x', 'y', size=5, color="navy", alpha=0.5, source=source)

# Streamlit app
st.title("Artificial Touch Simulation")

# Create a Streamlit container for the Bokeh plot
chart = st.bokeh_chart(p)

def update_points():
    global touch_points, velocities, is_affected
    
    # Apply spring force
    for i, (x, y) in enumerate(touch_points):
        force_x = (original_points[i][0] - x) * ELASTICITY
        force_y = (original_points[i][1] - y) * ELASTICITY
        velocities[i] = (velocities[i][0] + force_x, velocities[i][1] + force_y)
    
    # Apply damping
    for i, (vx, vy) in enumerate(velocities):
        velocities[i] = (vx * DAMPING, vy * DAMPING)
    
    # Update position
    for i, (x, y) in enumerate(touch_points):
        vx, vy = velocities[i]
        touch_points[i] = (x + vx, y + vy)
    
    # Reset affected flags
    is_affected = [False] * len(touch_points)
    
    # Update Bokeh data source
    source.data = dict(x=[x for x, y in touch_points], y=[y for x, y in touch_points])

def on_tap(event):
    global touch_points, velocities, is_affected
    
    x, y = event.x, event.y
    for i, (tx, ty) in enumerate(touch_points):
        distance = ((tx - x)**2 + (ty - y)**2)**0.5
        if distance < 30:
            force_x = (tx - x) / distance
            force_y = (ty - y) / distance
            velocities[i] = (velocities[i][0] - force_x * 10, velocities[i][1] - force_y * 10)
            is_affected[i] = True
    
    st.write(f"Touch at ({x:.2f}, {y:.2f})")
    update_points()

p.on_event(Tap, on_tap)

while True:
    update_points()
    chart.bokeh_chart(p)
    st.experimental_rerun()