生成无重叠的 0.2 mm Xynova 笔画图案
在打印页毫米坐标中筛选候选笔画,更新双 UV 产物。38 项测试通过;SVG 检查无交叠。
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""Physical-space clearance checks for capsule-shaped laser marks."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def point_segment_distance_sq(point, start, end):
|
||||
dx, dy = end[0] - start[0], end[1] - start[1]
|
||||
length_sq = dx * dx + dy * dy
|
||||
if length_sq == 0:
|
||||
return (point[0] - start[0]) ** 2 + (point[1] - start[1]) ** 2
|
||||
t = max(0.0, min(1.0, ((point[0] - start[0]) * dx + (point[1] - start[1]) * dy) / length_sq))
|
||||
return (point[0] - start[0] - t * dx) ** 2 + (point[1] - start[1] - t * dy) ** 2
|
||||
|
||||
|
||||
def segments_distance_sq(a0, a1, b0, b1):
|
||||
"""Minimum squared distance, including a proper crossing at zero."""
|
||||
def cross(p, q, r):
|
||||
return (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0])
|
||||
|
||||
ab0, ab1 = cross(a0, a1, b0), cross(a0, a1, b1)
|
||||
ba0, ba1 = cross(b0, b1, a0), cross(b0, b1, a1)
|
||||
if ab0 * ab1 < 0 and ba0 * ba1 < 0:
|
||||
return 0.0
|
||||
return min(
|
||||
point_segment_distance_sq(a0, b0, b1),
|
||||
point_segment_distance_sq(a1, b0, b1),
|
||||
point_segment_distance_sq(b0, a0, a1),
|
||||
point_segment_distance_sq(b1, a0, a1),
|
||||
)
|
||||
|
||||
|
||||
def capsule_segment(cx, cy, half_length, angle):
|
||||
dx, dy = half_length * math.cos(angle), half_length * math.sin(angle)
|
||||
return (cx - dx, cy - dy), (cx + dx, cy + dy)
|
||||
|
||||
|
||||
def has_clearance(candidate, accepted, clearance):
|
||||
"""Capsules are (start, end, radius), all in the same physical units."""
|
||||
start, end, radius = candidate
|
||||
for other_start, other_end, other_radius in accepted:
|
||||
limit = radius + other_radius + clearance
|
||||
if (max(start[0], end[0]) + limit < min(other_start[0], other_end[0])
|
||||
or max(other_start[0], other_end[0]) + limit < min(start[0], end[0])
|
||||
or max(start[1], end[1]) + limit < min(other_start[1], other_end[1])
|
||||
or max(other_start[1], other_end[1]) + limit < min(start[1], end[1])):
|
||||
continue
|
||||
if segments_distance_sq(start, end, other_start, other_end) < limit * limit:
|
||||
return False
|
||||
return True
|
||||
Reference in New Issue
Block a user