Spaces:
Sleeping
Sleeping
import streamlit as st | |
import numpy as np | |
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 | |
x = np.linspace(50, WIDTH-50, num_points) | |
y = np.linspace(50, HEIGHT-50, num_points) | |
xx, yy = np.meshgrid(x, y) | |
touch_points = np.column_stack((xx.ravel(), yy.ravel())) | |
original_points = touch_points.copy() | |
velocities = np.zeros_like(touch_points, dtype=np.bool_) | |
source = ColumnDataSource(data=dict(x=touch_points[:, 0], y=touch_points[:, 1])) | |
# 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 | |
# Apply spring force | |
force = (original_points - touch_points) * ELASTICITY | |
# Update velocity | |
velocities += force | |
# Apply damping | |
velocities *= DAMPING | |
# Update position | |
touch_points += velocities | |
# Update Bokeh data source | |
source.data = dict(x=touch_points[:, 0], y=touch_points[:, 1]) | |
def on_tap(event): | |
global touch_points, velocities | |
x, y = event.x, event.y | |
distances = np.sqrt(np.sum((touch_points - [x, y])**2, axis=1)) | |
affected = distances < 30 | |
force = (touch_points[affected] - [x, y]) / distances[affected, np.newaxis] | |
velocities[affected] -= force * 10 | |
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() |