From 233a67edf137857bd1de40990a423438d1d2a1d2 Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Wed, 15 Apr 2020 22:05:09 -0700 Subject: [PATCH 1/7] Attempting to write a parsing algorithm that's simple and works --- parse.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/parse.py b/parse.py index 2d44875..d3c771b 100644 --- a/parse.py +++ b/parse.py @@ -75,7 +75,58 @@ def determine_parts_list(schematic): return parts_list def determine_net_list(schematic): - print('NOT IMPLEMENTED') + wires = [ record for record in schematic["records"] if record["RECORD"] == "27" ] + contacts = [ record for record in schematic["records"] if record["RECORD"] == "2" ] + + wire_groups = [] + + p = re.compile('^(?PX)(?P\d+)$') + for wire in wires: + coord_name_matches = [x for x in [p.match(key) for key in wire.keys()] if x] + wire['coords'] = [ ( int(wire['X' + match.group('index')]) , int(wire['Y' + match.group('index')]) ) + for match in coord_name_matches ] + + group_counter = 0 + for wire_a in wires: + other_wires = [wire for wire in wires if wire["index"] != wire_a["index"]] + wire_a_vertex_pairs = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in + range(len(wire_a['coords']) - 1)] + + for wire_b in other_wires: + wire_b_vertex_pairs = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in + range(len(wire_b['coords']) - 1)] + + for vertex_a_pair in wire_a_vertex_pairs: + for vertex_b_pair in wire_b_vertex_pairs: + if ( (( vertex_a_pair[0][0] <= vertex_b_pair[0][0] <= vertex_a_pair[1][0] ) + and ( vertex_a_pair[0][1] <= vertex_b_pair[0][1] <= vertex_a_pair[1][1] )) + or (( vertex_a_pair[0][0] >= vertex_b_pair[0][0] >= vertex_a_pair[1][0] ) + and ( vertex_a_pair[0][1] >= vertex_b_pair[0][1] >= vertex_a_pair[1][1] )) + or (( vertex_a_pair[0][0] <= vertex_b_pair[1][0] <= vertex_a_pair[1][0] ) + and ( vertex_a_pair[0][1] <= vertex_b_pair[1][1] <= vertex_a_pair[1][1] )) + or (( vertex_a_pair[0][0] >= vertex_b_pair[1][0] >= vertex_a_pair[1][0] ) + and ( vertex_a_pair[0][1] >= vertex_b_pair[1][1] >= vertex_a_pair[1][1] )) )\ + or ( (( vertex_b_pair[0][0] <= vertex_a_pair[0][0] <= vertex_b_pair[1][0] ) + and ( vertex_b_pair[0][1] <= vertex_a_pair[0][1] <= vertex_b_pair[1][1] )) + or (( vertex_b_pair[0][0] >= vertex_a_pair[0][0] >= vertex_b_pair[1][0] ) + and ( vertex_b_pair[0][1] >= vertex_a_pair[0][1] >= vertex_b_pair[1][1] )) + or (( vertex_b_pair[0][0] <= vertex_a_pair[1][0] <= vertex_b_pair[1][0] ) + and ( vertex_b_pair[0][1] <= vertex_a_pair[1][1] <= vertex_b_pair[1][1] )) + or (( vertex_b_pair[0][0] >= vertex_a_pair[1][0] >= vertex_b_pair[1][0] ) + and ( vertex_b_pair[0][1] >= vertex_a_pair[1][1] >= vertex_b_pair[1][1] )) ): + print("line {0} intersects with line {1}".format(vertex_a_pair, vertex_b_pair)) + + + + if ( wire_a.get('group', None) != None ) and ( wire_b.get('group', None) == None ): + wire_b['group'] = wire_a['group'] + elif (wire_a.get('group', None) == None) and (wire_b.get('group', None) != None): + wire_a['group'] = wire_b['group'] + else: + wire_a['group'] = group_counter + wire_b['group'] = group_counter + group_counter += 1 + return schematic def main(args): From 6963b9a8cc868b7a0b963a75c7275e2818917195 Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Thu, 16 Apr 2020 15:18:16 -0700 Subject: [PATCH 2/7] Implemented a really sloppy way of finding nets --- parse.py | 111 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 45 deletions(-) diff --git a/parse.py b/parse.py index d3c771b..2d3193a 100644 --- a/parse.py +++ b/parse.py @@ -76,59 +76,80 @@ def determine_parts_list(schematic): def determine_net_list(schematic): wires = [ record for record in schematic["records"] if record["RECORD"] == "27" ] - contacts = [ record for record in schematic["records"] if record["RECORD"] == "2" ] - - wire_groups = [] p = re.compile('^(?PX)(?P\d+)$') for wire in wires: coord_name_matches = [x for x in [p.match(key) for key in wire.keys()] if x] wire['coords'] = [ ( int(wire['X' + match.group('index')]) , int(wire['Y' + match.group('index')]) ) for match in coord_name_matches ] - - group_counter = 0 - for wire_a in wires: - other_wires = [wire for wire in wires if wire["index"] != wire_a["index"]] - wire_a_vertex_pairs = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in - range(len(wire_a['coords']) - 1)] - - for wire_b in other_wires: - wire_b_vertex_pairs = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in - range(len(wire_b['coords']) - 1)] - - for vertex_a_pair in wire_a_vertex_pairs: - for vertex_b_pair in wire_b_vertex_pairs: - if ( (( vertex_a_pair[0][0] <= vertex_b_pair[0][0] <= vertex_a_pair[1][0] ) - and ( vertex_a_pair[0][1] <= vertex_b_pair[0][1] <= vertex_a_pair[1][1] )) - or (( vertex_a_pair[0][0] >= vertex_b_pair[0][0] >= vertex_a_pair[1][0] ) - and ( vertex_a_pair[0][1] >= vertex_b_pair[0][1] >= vertex_a_pair[1][1] )) - or (( vertex_a_pair[0][0] <= vertex_b_pair[1][0] <= vertex_a_pair[1][0] ) - and ( vertex_a_pair[0][1] <= vertex_b_pair[1][1] <= vertex_a_pair[1][1] )) - or (( vertex_a_pair[0][0] >= vertex_b_pair[1][0] >= vertex_a_pair[1][0] ) - and ( vertex_a_pair[0][1] >= vertex_b_pair[1][1] >= vertex_a_pair[1][1] )) )\ - or ( (( vertex_b_pair[0][0] <= vertex_a_pair[0][0] <= vertex_b_pair[1][0] ) - and ( vertex_b_pair[0][1] <= vertex_a_pair[0][1] <= vertex_b_pair[1][1] )) - or (( vertex_b_pair[0][0] >= vertex_a_pair[0][0] >= vertex_b_pair[1][0] ) - and ( vertex_b_pair[0][1] >= vertex_a_pair[0][1] >= vertex_b_pair[1][1] )) - or (( vertex_b_pair[0][0] <= vertex_a_pair[1][0] <= vertex_b_pair[1][0] ) - and ( vertex_b_pair[0][1] <= vertex_a_pair[1][1] <= vertex_b_pair[1][1] )) - or (( vertex_b_pair[0][0] >= vertex_a_pair[1][0] >= vertex_b_pair[1][0] ) - and ( vertex_b_pair[0][1] >= vertex_a_pair[1][1] >= vertex_b_pair[1][1] )) ): - print("line {0} intersects with line {1}".format(vertex_a_pair, vertex_b_pair)) - - - - if ( wire_a.get('group', None) != None ) and ( wire_b.get('group', None) == None ): - wire_b['group'] = wire_a['group'] - elif (wire_a.get('group', None) == None) and (wire_b.get('group', None) != None): - wire_a['group'] = wire_b['group'] - else: - wire_a['group'] = group_counter - wire_b['group'] = group_counter - group_counter += 1 - + + nets = [] + for wire in wires: + if wire["index"] not in [id for net in nets for id in net]: + nets.append(find_connected_wires(wire, [], schematic)) + + schematic["nets"] = nets + return schematic +def find_connected_wires(wire, visited, schematic): + neighbors = find_neighbors(wire, schematic) + print('entering: {0}'.format(wire['index'])) + + if wire['index'] not in visited: + print('adding: {0} to {1}'.format(wire['index'], visited)) + visited.append(wire['index']) + + for neighbor in neighbors: + print('trying: {0} of {1}'.format(neighbor['index'], [x['index'] for x in neighbors])) + visited = find_connected_wires(neighbor, visited, schematic) + print('visited = {0}'.format(visited)) + else: + print('skipping: {0} already in list {1}'.format(wire['index'], visited)) + + print('returning: {0}'.format(wire['index'])) + return visited + +def find_neighbors(wire, schematic): + all_wires = [record for record in schematic["records"] if record["RECORD"] == "27"] + other_wires = [record for record in all_wires if record != wire] + + neighbors = [] + for other_wire in other_wires: + if is_connected(wire, other_wire): + neighbors.append(other_wire) + + return neighbors + +def is_connected(wire_a, wire_b): + a_vertex_pairs = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in + range(len(wire_a['coords']) - 1)] + b_vertex_pairs = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in + range(len(wire_b['coords']) - 1)] + + for a_vx_pair in a_vertex_pairs: + for b_vx_pair in b_vertex_pairs: + if (((a_vx_pair[0][0] <= b_vx_pair[0][0] <= a_vx_pair[1][0]) + and (a_vx_pair[0][1] <= b_vx_pair[0][1] <= a_vx_pair[1][1])) + or ((a_vx_pair[0][0] >= b_vx_pair[0][0] >= a_vx_pair[1][0]) + and (a_vx_pair[0][1] >= b_vx_pair[0][1] >= a_vx_pair[1][1])) + or ((a_vx_pair[0][0] <= b_vx_pair[1][0] <= a_vx_pair[1][0]) + and (a_vx_pair[0][1] <= b_vx_pair[1][1] <= a_vx_pair[1][1])) + or ((a_vx_pair[0][0] >= b_vx_pair[1][0] >= a_vx_pair[1][0]) + and (a_vx_pair[0][1] >= b_vx_pair[1][1] >= a_vx_pair[1][1])))\ + or (((b_vx_pair[0][0] <= a_vx_pair[0][0] <= b_vx_pair[1][0]) + and (b_vx_pair[0][1] <= a_vx_pair[0][1] <= b_vx_pair[1][1])) + or ((b_vx_pair[0][0] >= a_vx_pair[0][0] >= b_vx_pair[1][0]) + and (b_vx_pair[0][1] >= a_vx_pair[0][1] >= b_vx_pair[1][1])) + or ((b_vx_pair[0][0] <= a_vx_pair[1][0] <= b_vx_pair[1][0]) + and (b_vx_pair[0][1] <= a_vx_pair[1][1] <= b_vx_pair[1][1])) + or ((b_vx_pair[0][0] >= a_vx_pair[1][0] >= b_vx_pair[1][0]) + and (b_vx_pair[0][1] >= a_vx_pair[1][1] >= b_vx_pair[1][1]))): + + return True + + return False + def main(args): schematic = parse(**vars(args)) From 478ea80e62b98a79ac975b58b25ef0c63c80a811 Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Thu, 21 May 2020 16:55:54 -0700 Subject: [PATCH 3/7] Making the is_connected logic more understandable, Add spurious altium .NET file to ignore --- .gitignore | 1 + parse.py | 41 ++++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index a3a21b8..874273e 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ Temporary Items *.OutJob *.SchDoc.Zip *.OutJob.Zip +*.NET diff --git a/parse.py b/parse.py index 2d3193a..3797ce9 100644 --- a/parse.py +++ b/parse.py @@ -122,30 +122,29 @@ def find_neighbors(wire, schematic): return neighbors def is_connected(wire_a, wire_b): - a_vertex_pairs = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in + a_line_segments = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in range(len(wire_a['coords']) - 1)] - b_vertex_pairs = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in + b_line_segments = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in range(len(wire_b['coords']) - 1)] - for a_vx_pair in a_vertex_pairs: - for b_vx_pair in b_vertex_pairs: - if (((a_vx_pair[0][0] <= b_vx_pair[0][0] <= a_vx_pair[1][0]) - and (a_vx_pair[0][1] <= b_vx_pair[0][1] <= a_vx_pair[1][1])) - or ((a_vx_pair[0][0] >= b_vx_pair[0][0] >= a_vx_pair[1][0]) - and (a_vx_pair[0][1] >= b_vx_pair[0][1] >= a_vx_pair[1][1])) - or ((a_vx_pair[0][0] <= b_vx_pair[1][0] <= a_vx_pair[1][0]) - and (a_vx_pair[0][1] <= b_vx_pair[1][1] <= a_vx_pair[1][1])) - or ((a_vx_pair[0][0] >= b_vx_pair[1][0] >= a_vx_pair[1][0]) - and (a_vx_pair[0][1] >= b_vx_pair[1][1] >= a_vx_pair[1][1])))\ - or (((b_vx_pair[0][0] <= a_vx_pair[0][0] <= b_vx_pair[1][0]) - and (b_vx_pair[0][1] <= a_vx_pair[0][1] <= b_vx_pair[1][1])) - or ((b_vx_pair[0][0] >= a_vx_pair[0][0] >= b_vx_pair[1][0]) - and (b_vx_pair[0][1] >= a_vx_pair[0][1] >= b_vx_pair[1][1])) - or ((b_vx_pair[0][0] <= a_vx_pair[1][0] <= b_vx_pair[1][0]) - and (b_vx_pair[0][1] <= a_vx_pair[1][1] <= b_vx_pair[1][1])) - or ((b_vx_pair[0][0] >= a_vx_pair[1][0] >= b_vx_pair[1][0]) - and (b_vx_pair[0][1] >= a_vx_pair[1][1] >= b_vx_pair[1][1]))): - + # check if any vertices in wire_a lie on wire_b + for vertex in [vx for line in a_line_segments for vx in line]: + for b_line in b_line_segments: + b_xs = sorted(list(zip(*b_line))[0]) + b_ys = sorted(list(zip(*b_line))[1]) + + if ((min(b_xs) <= vertex[0] <= max(b_xs)) + and (min(b_ys) <= vertex[1] <= max(b_ys))): + return True + + # check if any vertices in wire_b lie on wire_a + for vertex in [vx for line in b_line_segments for vx in line]: + for a_line in a_line_segments: + a_xs = sorted(list(zip(*a_line))[0]) + a_ys = sorted(list(zip(*a_line))[1]) + + if ((min(a_xs) <= vertex[0] <= max(a_xs)) + and (min(a_ys) <= vertex[1] <= max(a_ys))): return True return False From 3c16630df46d2f15d36efe00b7387707064e2beb Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Thu, 21 May 2020 19:54:15 -0700 Subject: [PATCH 4/7] Store complete wire information within netlist object, Begin implementing a generic record search function --- parse.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/parse.py b/parse.py index 3797ce9..cff8870 100644 --- a/parse.py +++ b/parse.py @@ -76,6 +76,7 @@ def determine_parts_list(schematic): def determine_net_list(schematic): wires = [ record for record in schematic["records"] if record["RECORD"] == "27" ] + pins = [ record for record in schematic["records"] if record["RECORD"] == 2 ] p = re.compile('^(?PX)(?P\d+)$') for wire in wires: @@ -88,24 +89,50 @@ def determine_net_list(schematic): if wire["index"] not in [id for net in nets for id in net]: nets.append(find_connected_wires(wire, [], schematic)) + visited, found = find_record(schematic, key="RECORD", value="2") + schematic["nets"] = nets return schematic +def find_record(schematic, key, value, record=None, visited=None, found=None): + print("finding records where: {0} = {1}".format(key, value)) + + if visited == None: + visited = [] + if found == None: + found = [] + if record == None: + for record in schematic['records']: + visited, found = find_record(schematic, key, value, record=record, visited=visited, found=found) + else: + if record['index'] not in [r['index'] for r in visited]: + visited.append(record) + + if key in record.keys(): + if record[key] == value: + found.append(record) + + if "children" in record.keys(): + for child_record in record["children"]: + visited, found = find_record(schematic, key, value, record=child_record, visited=visited, found=found) + + return visited, found + def find_connected_wires(wire, visited, schematic): neighbors = find_neighbors(wire, schematic) print('entering: {0}'.format(wire['index'])) - if wire['index'] not in visited: - print('adding: {0} to {1}'.format(wire['index'], visited)) - visited.append(wire['index']) + if wire['index'] not in [w['index'] for w in visited]: + print('adding: {0} to {1}'.format(wire['index'], [w['index'] for w in visited])) + visited.append(wire) for neighbor in neighbors: print('trying: {0} of {1}'.format(neighbor['index'], [x['index'] for x in neighbors])) visited = find_connected_wires(neighbor, visited, schematic) - print('visited = {0}'.format(visited)) + print('visited = {0}'.format([w['index'] for w in visited])) else: - print('skipping: {0} already in list {1}'.format(wire['index'], visited)) + print('skipping: {0} already in list {1}'.format(wire['index'], [w['index'] for w in visited])) print('returning: {0}'.format(wire['index'])) return visited From cbe42461b18b96de5fa76b5cff5cbaf6a6b5489d Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Thu, 21 May 2020 22:30:41 -0700 Subject: [PATCH 5/7] Attempt to find pins on each net --- parse.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/parse.py b/parse.py index cff8870..10a3833 100644 --- a/parse.py +++ b/parse.py @@ -3,6 +3,8 @@ import olefile import re import json import copy +import logging as lg +lg.basicConfig(level=lg.INFO) def parse(input, format, **kwargs): fullPath = input @@ -89,14 +91,22 @@ def determine_net_list(schematic): if wire["index"] not in [id for net in nets for id in net]: nets.append(find_connected_wires(wire, [], schematic)) - visited, found = find_record(schematic, key="RECORD", value="2") + _, pins = find_record(schematic, key="RECORD", value="2") + + for net in nets: + for wire in net: + for vertex in wire['coords']: + for pin in pins: + if ( vertex[0] == int(pin['LOCATION.X']) + and vertex[1] == int(pin['LOCATION.Y']) ): + lg.debug('found pin {0} on net {1}'.format(pin, net)) schematic["nets"] = nets return schematic def find_record(schematic, key, value, record=None, visited=None, found=None): - print("finding records where: {0} = {1}".format(key, value)) + lg.debug("finding records where: {0} = {1}".format(key, value)) if visited == None: visited = [] @@ -121,20 +131,20 @@ def find_record(schematic, key, value, record=None, visited=None, found=None): def find_connected_wires(wire, visited, schematic): neighbors = find_neighbors(wire, schematic) - print('entering: {0}'.format(wire['index'])) + lg.debug('entering: {0}'.format(wire['index'])) if wire['index'] not in [w['index'] for w in visited]: - print('adding: {0} to {1}'.format(wire['index'], [w['index'] for w in visited])) + lg.debug('adding: {0} to {1}'.format(wire['index'], [w['index'] for w in visited])) visited.append(wire) for neighbor in neighbors: - print('trying: {0} of {1}'.format(neighbor['index'], [x['index'] for x in neighbors])) + lg.debug('trying: {0} of {1}'.format(neighbor['index'], [x['index'] for x in neighbors])) visited = find_connected_wires(neighbor, visited, schematic) - print('visited = {0}'.format([w['index'] for w in visited])) + lg.debug('visited = {0}'.format([w['index'] for w in visited])) else: - print('skipping: {0} already in list {1}'.format(wire['index'], [w['index'] for w in visited])) + lg.debug('skipping: {0} already in list {1}'.format(wire['index'], [w['index'] for w in visited])) - print('returning: {0}'.format(wire['index'])) + lg.debug('returning: {0}'.format(wire['index'])) return visited def find_neighbors(wire, schematic): From c39f4375cfba8e7e4d4bcc55a06de2a64fb8f808 Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Fri, 22 May 2020 17:20:23 -0700 Subject: [PATCH 6/7] Expand net finding to include Power Ports and Net Labels, Hijack find_connected_wires for this purpose --- parse.py | 74 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/parse.py b/parse.py index 10a3833..6c9f10e 100644 --- a/parse.py +++ b/parse.py @@ -3,8 +3,9 @@ import olefile import re import json import copy +import math import logging as lg -lg.basicConfig(level=lg.INFO) +lg.basicConfig(level=lg.DEBUG) def parse(input, format, **kwargs): fullPath = input @@ -77,34 +78,39 @@ def determine_parts_list(schematic): return parts_list def determine_net_list(schematic): - wires = [ record for record in schematic["records"] if record["RECORD"] == "27" ] - pins = [ record for record in schematic["records"] if record["RECORD"] == 2 ] + _, wires = find_record(schematic, key="RECORD", value="27") + _, pins = find_record(schematic, key="RECORD", value="2") + _, labels = find_record(schematic, key="RECORD", value="25") + _, power_ports = find_record(schematic, key="RECORD", value="17") + devices = wires + pins + labels + power_ports p = re.compile('^(?PX)(?P\d+)$') - for wire in wires: - coord_name_matches = [x for x in [p.match(key) for key in wire.keys()] if x] - wire['coords'] = [ ( int(wire['X' + match.group('index')]) , int(wire['Y' + match.group('index')]) ) - for match in coord_name_matches ] + for device in devices: + # if a Pin, do some fancy geometry math + if device["RECORD"] == "2": + rotation = (int(device["PINCONGLOMERATE"]) & 0x03) * 90 + device['coords'] = [[ + int(int(device['LOCATION.X']) + math.cos(rotation / 180 * math.pi) * int(device['PINLENGTH'])), + int(int(device['LOCATION.Y']) + math.sin(rotation / 180 * math.pi) * int(device['PINLENGTH'])) + ]] + # if a Wire, follow inconsistent location key names (X1 vs LOCATION.X, etc..) + elif device["RECORD"] == "27": + coord_name_matches = [x for x in [p.match(key) for key in device.keys()] if x] + device['coords'] = [ ( int(device['X' + match.group('index')]) , int(device['Y' + match.group('index')]) ) + for match in coord_name_matches ] + # everything else, just convert the location values to ints + else: + device['coords'] = [(int(device['LOCATION.X']), int(device['LOCATION.Y']))] nets = [] - for wire in wires: - if wire["index"] not in [id for net in nets for id in net]: - nets.append(find_connected_wires(wire, [], schematic)) - - _, pins = find_record(schematic, key="RECORD", value="2") - - for net in nets: - for wire in net: - for vertex in wire['coords']: - for pin in pins: - if ( vertex[0] == int(pin['LOCATION.X']) - and vertex[1] == int(pin['LOCATION.Y']) ): - lg.debug('found pin {0} on net {1}'.format(pin, net)) + for device in devices: + if device["index"] not in [d['index'] for net in nets for d in net]: + nets.append(find_connected_wires(device, devices, [], schematic)) schematic["nets"] = nets return schematic - + def find_record(schematic, key, value, record=None, visited=None, found=None): lg.debug("finding records where: {0} = {1}".format(key, value)) @@ -129,8 +135,8 @@ def find_record(schematic, key, value, record=None, visited=None, found=None): return visited, found -def find_connected_wires(wire, visited, schematic): - neighbors = find_neighbors(wire, schematic) +def find_connected_wires(wire, devices, visited, schematic): + neighbors = find_neighbors(wire, devices, schematic) lg.debug('entering: {0}'.format(wire['index'])) if wire['index'] not in [w['index'] for w in visited]: @@ -139,7 +145,7 @@ def find_connected_wires(wire, visited, schematic): for neighbor in neighbors: lg.debug('trying: {0} of {1}'.format(neighbor['index'], [x['index'] for x in neighbors])) - visited = find_connected_wires(neighbor, visited, schematic) + visited = find_connected_wires(neighbor, devices, visited, schematic) lg.debug('visited = {0}'.format([w['index'] for w in visited])) else: lg.debug('skipping: {0} already in list {1}'.format(wire['index'], [w['index'] for w in visited])) @@ -147,8 +153,8 @@ def find_connected_wires(wire, visited, schematic): lg.debug('returning: {0}'.format(wire['index'])) return visited -def find_neighbors(wire, schematic): - all_wires = [record for record in schematic["records"] if record["RECORD"] == "27"] +def find_neighbors(wire, devices, schematic): + all_wires = devices other_wires = [record for record in all_wires if record != wire] neighbors = [] @@ -159,10 +165,18 @@ def find_neighbors(wire, schematic): return neighbors def is_connected(wire_a, wire_b): - a_line_segments = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in + + if wire_a["RECORD"] == "27": + a_line_segments = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in range(len(wire_a['coords']) - 1)] - b_line_segments = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in + else: + a_line_segments = [(wire_a['coords'][0], wire_a['coords'][0])] + + if wire_b["RECORD"] == "27": + b_line_segments = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in range(len(wire_b['coords']) - 1)] + else: + b_line_segments = [(wire_b['coords'][0], wire_b['coords'][0])] # check if any vertices in wire_a lie on wire_b for vertex in [vx for line in a_line_segments for vx in line]: @@ -183,6 +197,10 @@ def is_connected(wire_a, wire_b): if ((min(a_xs) <= vertex[0] <= max(a_xs)) and (min(a_ys) <= vertex[1] <= max(a_ys))): return True + + # check if both items are Power Ports with the same TEXT value + if ( wire_a["RECORD"] == "17" ) and ( wire_b["RECORD"] == "17" ) and ( wire_a["TEXT"] == wire_b["TEXT"] ): + return True return False From a1d0f6247fb537ca639a739abf848119d570cbad Mon Sep 17 00:00:00 2001 From: Aaron Goldstein Date: Thu, 4 Jun 2020 06:53:17 -0700 Subject: [PATCH 7/7] Name nets automatically based on their contents, which I think is how altium does it... Also, add more random altium output files to ignore. --- .gitignore | 1 + parse.py | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 874273e..552ccc3 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ Temporary Items *.SchDoc.Zip *.OutJob.Zip *.NET +*.PcbDoc.htm diff --git a/parse.py b/parse.py index 6c9f10e..056833a 100644 --- a/parse.py +++ b/parse.py @@ -48,6 +48,13 @@ def parse(input, format, **kwargs): return schematic def determine_hierarchy(schematic): + """Convert a dict containing a flat list of records + into a dict of records in a hierarchy + + :param schematic: dict with 'header' and 'records' populated + :return: the input dict with 'records' assembled into parent/child hierarchy + """ + # prep a scratchpad copy of records to build hierarchy from records_copy = copy.deepcopy(schematic["records"]) schematic["hierarchy"] = [] @@ -104,8 +111,20 @@ def determine_net_list(schematic): nets = [] for device in devices: - if device["index"] not in [d['index'] for net in nets for d in net]: - nets.append(find_connected_wires(device, devices, [], schematic)) + if device["index"] not in [d['index'] for net in nets for d in net['devices']]: + net = {'name': None, + 'devices': find_connected_wires(device, devices, [], schematic)} + nets.append(net) + + for net in nets: + net['devices'].sort(key=lambda k: k['index']) + if not net['name']: + net['name'] = next(iter(d['TEXT'] for d in net['devices'] if ((d['RECORD'] == '17') or (d['RECORD'] == '25'))), None) + + if not net['name']: + naming_pin = next(iter(d for d in net['devices'] if d['RECORD'] == '2'), None) + parent = next(iter(find_record(schematic, key="index", value=int(naming_pin['OWNERINDEX']))[1]), None) if naming_pin else None + net['name'] = next(iter('Net' + r['TEXT'] for r in parent['children'] if (r['RECORD'] == '34')), None) if parent else None schematic["nets"] = nets