-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextract.py
More file actions
128 lines (107 loc) · 5.49 KB
/
Copy pathextract.py
File metadata and controls
128 lines (107 loc) · 5.49 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from gerbonara.graphic_objects import Line
from gerbonara.apertures import CircleAperture
from debug import plot_zones
def round_to_resolution(value, resolution):
"""Rounds a value to the nearest multiple of the resolution."""
return round(value / resolution) * resolution
def extract_socket_locations(gerber, net_diameter_mapping, resolution, legacy_sockets=False):
"""
Extracts the locations of the Gerber Sockets from a Gerber file.
Paramaters:
gerber (GerberFile): The Gerber file object from gerbonara.
sockets_diameter_mapping (dict): A dictionary mapping net names to their assigned diameters.
Example format: {"JD_PWR": 0.11, "JD_GND": 0.12, "JD_DATA": 0.13}
resolution (float): The resolution of the grid, for scaling the socket and segment coordinates.
Returns:
socket_locations (dict): A dictionary containing net names as keys and a list of socket locations as values.
Each socket location is represented as a tuple of (x, y) coordinates.
"""
diameter_to_net = {value: key for key, value in net_diameter_mapping.items()}
socket_locations = {}
if not gerber.objects:
print("No objects found in a GerberSocket file.")
for obj in gerber.objects:
if hasattr(obj, 'aperture') and isinstance(obj.aperture, CircleAperture):
diameter = obj.aperture.diameter
if diameter in diameter_to_net:
net_name = diameter_to_net[diameter]
if isinstance(obj, Line): # Assuming lines are used to represent sockets
location = (
round_to_resolution(obj.x1, resolution),
round_to_resolution(obj.y1, resolution)
)
socket_locations.setdefault(net_name, []).append(location)
return socket_locations
def extract_keep_out_zones(gerber, keep_out_zone_aperture_diameter, module_margin, resolution, debug=True):
"""
Extracts and returns a list of rectangles representing the keep-out zones from the given Gerber object.
Parameters:
gerber (GerberFile): The Gerber file object from gerbonara.
resolution (float): The resolution of the grid, for scaling the socket and segment coordinates.
aperture_diameter (float): The diameter (in mm) of the aperture used to trace out the keep-out zones. Defaults to 0.1.
margin (int): The margin to add to the keep-out zones. Defaults to 1mm.
debug (bool): If True, the function will draw the keep-out zones on a separate Gerber file. Defaults to False.
Returns:
rectangles (tuple list): A list of tuples representing the rectangles of the keep-out zones.
Each tuple contains four points in the order (top_left, top_right, bottom_right, bottom_left).
"""
lines = [obj for obj in gerber.objects if isinstance(obj, Line) and
isinstance(obj.aperture, CircleAperture) and
abs(obj.aperture.diameter - keep_out_zone_aperture_diameter) < 0.0001]
rectangles = []
used_indices = set()
def find_continuation(current_index):
current_line = lines[current_index]
x2, y2 = current_line.x2, current_line.y2
for index, line in enumerate(lines):
if index not in used_indices and index != current_index:
# Check connection
if (line.x1 == x2 and line.y1 == y2) or (line.x2 == x2 and line.y2 == y2):
return index
return None
for index, line in enumerate(lines):
if index in used_indices:
continue
current_index = index
rectangle_indices = [current_index]
for _ in range(3):
next_index = find_continuation(current_index)
if next_index is not None:
rectangle_indices.append(next_index)
current_index = next_index
else:
break
if len(rectangle_indices) == 4:
rectangle_lines = [lines[i] for i in rectangle_indices]
if rectangle_lines[0].x1 == rectangle_lines[-1].x2 and rectangle_lines[0].y1 == rectangle_lines[-1].y2:
points = set((line.x1, line.y1) for line in rectangle_lines) | set((line.x2, line.y2) for line in rectangle_lines)
if len(points) == 4:
rounded_points = {
(round_to_resolution(p[0], resolution), round_to_resolution(p[1], resolution))
for p in points
}
sorted_points = sorted(rounded_points, key=lambda p: (p[0], p[1])) # Sort primarily by x, secondarily by y
bottom_left = sorted_points[0][0] - module_margin, sorted_points[0][1] - module_margin
top_left = sorted_points[1][0] - module_margin, sorted_points[1][1] + module_margin
top_right = sorted_points[3][0] + module_margin, sorted_points[3][1] + module_margin
bottom_right = sorted_points[2][0] + module_margin, sorted_points[2][1] - module_margin
rectangles.append((bottom_left, top_left, top_right, bottom_right))
used_indices.update(rectangle_indices)
if debug:
plot_zones(rectangles, output_file="debug_margin.gbr")
return rectangles
# *
# \
# \
# |\
# \ | \ (__)
# \\|| \(oo)
# \||\ \\/
# ~~ \||
# \\ ||
# \\||
# \||
# ~~
# \\_
# \_
# Cow skiing a Black Diamond at Aspen