diff options
Diffstat (limited to 'examples/excellon_optimize.py')
-rw-r--r-- | examples/excellon_optimize.py | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/examples/excellon_optimize.py b/examples/excellon_optimize.py new file mode 100644 index 0000000..5f0adbc --- /dev/null +++ b/examples/excellon_optimize.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Example using pcb-tools with tsp-solver (github.com/dmishin/tsp-solver) to +# optimize tool paths in an Excellon file. +# +# +# Copyright 2015 Hamilton Kibbe <ham@hamiltonkib.be> +# Based on a script by https://github.com/koppi +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +import sys +import math +import gerber +from operator import sub +from gerber.excellon import DrillHit + +try: + from tsp_solver.greedy import solve_tsp +except ImportError: + print('\n=================================================================\n' + 'This example requires tsp-solver be installed in order to run.\n\n' + 'tsp-solver can be downloaded from:\n' + ' http://github.com/dmishin/tsp-solver.\n' + '=================================================================') + sys.exit(0) + + +if __name__ == '__main__': + + # Get file name to open + if len(sys.argv) < 2: + fname = 'gerbers/shld.drd' + else: + fname = sys.argv[1] + + # Read the excellon file + f = gerber.read(fname) + + positions = {} + tools = {} + hit_counts = f.hit_count() + oldpath = sum(f.path_length().values()) + + #Get hit positions + for hit in f.hits: + tool_num = hit.tool.number + if tool_num not in positions.keys(): + positions[tool_num] = [] + positions[tool_num].append(hit.position) + + hits = [] + + # Optimize tool path for each tool + for tool, count in iter(hit_counts.items()): + + # Calculate distance matrix + distance_matrix = [[math.hypot(*tuple(map(sub, + positions[tool][i], + positions[tool][j]))) + for j in iter(range(count))] + for i in iter(range(count))] + + # Calculate new path + path = solve_tsp(distance_matrix, 50) + + # Create new hits list + hits += [DrillHit(f.tools[tool], positions[tool][p]) for p in path] + + # Update the file + f.hits = hits + f.filename = f.filename + '.optimized' + f.write() + + # Print drill report + print(f.report()) + print('Original path length: %1.4f' % oldpath) + print('Optimized path length: %1.4f' % sum(f.path_length().values())) + |