Spaces:
Runtime error
Runtime error
| 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 |