Spaces:
Sleeping
Sleeping
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() |