AnasSarkiz/muse-voice-remote

Muse Voice Remote — bare ESP32-S3R8, 155 TOP JLCPCB parts with real supplier CAD, native 3D assembly and GLB exports. Revised 17 mm case allocation; 0.30 mm via drill /0.45 mm pad. Checked prototype PCB; mechanical, RF and MUSE qualification pending.

Version
1.3.2
License
unset
Stars
0

scripts/precise_path.py

"""Visibility-simplified route through a constrained free-space triangulation."""
import heapq,math
from shapely import constrained_delaunay_triangles
from shapely.geometry import Point,LineString

def visible_path(region,start,end):
 if region.covers(LineString([start,end])):return [start,end]
 triangles=list(constrained_delaunay_triangles(region).geoms)
 starts=[i for i,t in enumerate(triangles) if t.covers(Point(start))]
 goals={i for i,t in enumerate(triangles) if t.covers(Point(end))}
 if not starts or not goals:raise RuntimeError('Triangulation does not contain fanout endpoints')
 centres=[(t.centroid.x,t.centroid.y) for t in triangles];edges={};neighbors=[[] for _ in triangles]
 for i,t in enumerate(triangles):
  vertices=list(t.exterior.coords)[:-1]
  for a,b in zip(vertices,vertices[1:]+vertices[:1]):
   key=tuple(sorted((a,b)))
   if key in edges:
    j=edges[key];mid=((a[0]+b[0])/2,(a[1]+b[1])/2);length=math.dist(centres[i],mid)+math.dist(mid,centres[j]);neighbors[i].append((j,mid,length));neighbors[j].append((i,mid,length))
   else:edges[key]=i
 cost={i:math.dist(start,centres[i]) for i in starts};queue=[(cost[i],i) for i in starts];heapq.heapify(queue);previous={};target=None
 while queue:
  score,i=heapq.heappop(queue)
  if score>cost[i]:continue
  if i in goals:target=i;break
  for j,mid,length in neighbors[i]:
   candidate=score+length
   if candidate<cost.get(j,math.inf):cost[j]=candidate;previous[j]=(i,mid);heapq.heappush(queue,(candidate,j))
 if target is None:raise RuntimeError('No constrained fanout path')
 chain=[target]
 while chain[-1] in previous:chain.append(previous[chain[-1]][0])
 chain.reverse();points=[start,centres[chain[0]]]
 for i,j in zip(chain,chain[1:]):points.extend([previous[j][1],centres[j]])
 points.append(end);simple=[points[0]];position=0
 while position<len(points)-1:
  candidate=len(points)-1
  while candidate>position+1 and not region.covers(LineString([points[position],points[candidate]])):candidate-=1
  simple.append(points[candidate]);position=candidate
 return simple