Spaces:
Runtime error
Runtime error
File size: 2,585 Bytes
910e0d4 | 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 76 77 78 79 80 81 | import numpy as np
from typing import List, Tuple
import math
def robust_merge_lines(lines: List[Tuple[float, float, float, float]],
angle_thresh: float = 5.0,
dist_thresh: float = 5.0) -> List[Tuple[float, float, float, float]]:
"""
Merge similar line segments using angle and distance thresholds.
Args:
lines: List of line segments [(x1,y1,x2,y2),...]
angle_thresh: Maximum angle difference in degrees
dist_thresh: Maximum endpoint distance
Returns:
List of merged line segments
"""
if not lines:
return []
# Convert to numpy array for easier manipulation
lines = np.array(lines)
# Calculate line angles
angles = np.arctan2(lines[:,3] - lines[:,1],
lines[:,2] - lines[:,0])
angles = np.degrees(angles) % 180
# Group similar lines
merged = []
used = set()
for i, line1 in enumerate(lines):
if i in used:
continue
# Find similar lines
similar = []
for j, line2 in enumerate(lines):
if j in used:
continue
# Check angle difference
angle_diff = abs(angles[i] - angles[j])
angle_diff = min(angle_diff, 180 - angle_diff)
if angle_diff > angle_thresh:
continue
# Check endpoint distances
dist1 = np.linalg.norm(line1[:2] - line2[:2])
dist2 = np.linalg.norm(line1[2:] - line2[2:])
if min(dist1, dist2) > dist_thresh:
continue
similar.append(j)
used.add(j)
# Merge similar lines
if similar:
points = lines[similar].reshape(-1, 2)
direction = np.array([np.cos(np.radians(angles[i])),
np.sin(np.radians(angles[i]))])
# Project points onto line direction
proj = points @ direction
# Get extreme points
min_idx = np.argmin(proj)
max_idx = np.argmax(proj)
merged_line = np.concatenate([points[min_idx], points[max_idx]])
merged.append(tuple(merged_line))
return merged
def compute_line_angle(x1: float, y1: float, x2: float, y2: float) -> float:
"""Compute angle of line segment in degrees"""
return math.degrees(math.atan2(y2 - y1, x2 - x1)) % 180 |