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