Porównaj commity

...

2 Commity

Autor SHA1 Wiadomość Data
Howard DaCosta 13596f9fcf db logic integrated to custom grid creation 2022-03-31 13:34:40 -04:00
Howard DaCosta 858529f128 integration of SQL db into wire combination logic
Inclusion of db allows for easier detection of wire groups and user-created interpolation wires. However, it seems to greatly increase the time of computation. Future work includes (1) investigating more efficient db methods and (2) doing garbage collection on irrelevant wire data
2022-03-31 12:46:34 -04:00
4 zmienionych plików z 231 dodań i 75 usunięć

BIN
.DS_Store vendored

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -1,8 +1,10 @@
from argparse import ArgumentParser
from ast import Return
import inkex
from inkex import Polyline, PathElement
from lxml import etree
from sympy import Segment, Point
from wiredb_proxy import WireDBProxy
class Connector():
'''
@ -56,6 +58,7 @@ class CombineGridsWorker():
self.wires = []
self.interpolation_wires = [] # for custom combination routing
self.connector = None
self.wiredb_proxy = WireDBProxy()
def group_wires(self, wires):
@ -64,33 +67,81 @@ class CombineGridsWorker():
Need to group them together so they get connected together
Need to fix this for when wire groups are angled (Same x/y won't apply)
TODO: integrate IDs somehow
'''
wire_groups = {}
# if self.is_horizontal_connection: # wires will have same x
for w_points in wires:
# points = [p for p in w.path.end_points]
p = w_points[0]
key = p.x if self.is_horizontal_connection else p.y
if key not in wire_groups:
wire_groups[key] = [w_points]
else:
wire_groups[key].append(w_points)
for k in wire_groups:
if self.is_horizontal_connection: # sort wires from top to bottom
wire_groups[k] = sorted(wire_groups[k], key=lambda w:-w[0].y)
else: # sort wires from left to right
wire_groups[k] = sorted(wire_groups[k], key=lambda w:w[0].x)
wire_groups = {}
wire_ids = [wire.get_id() for wire in wires]
id_to_wire = {wire.get_id() : wire for wire in wires}
wires_allocated = []
while len(wires_allocated) != len(wire_ids):
for idx, w_id in enumerate(wire_ids):
if w_id not in wires_allocated:
wire_group = self.wiredb_proxy.retrieve_wire_group_with_id(w_id)
if wire_group == []: # interpolation wire!
inkex.errormsg("points of interp wire @ group detetction:{}".format(len([[p.x,p.y] for p in wires[idx].path.end_points])))
self.interpolation_wires.append(wires[idx])
wires_allocated.append(wires[idx])
else:
if self.is_horizontal_connection: # sort wires from top to bottom
wire_group = sorted(wire_group, key=lambda w:-[p for p in id_to_wire[w].path.end_points][0].y)
else: # sort wires from left to right
wire_group = sorted(wire_group, key=lambda w: [p for p in id_to_wire[w].path.end_points][0].x)
wire_groups[min(wire_group)] = [id_to_wire[id] for id in wire_group] # get wire object of id
wires_allocated.extend(wire_group)
# OLD
# if self.is_horizontal_connection: # wires will have same x
# for w_points in wires:
# # points = [p for p in w.path.end_points]
# p = w_points[0]
# key = p.x if self.is_horizontal_connection else p.y
# if key not in wire_groups:
# wire_groups[key] = [w_points]
# else:
# wire_groups[key].append(w_points)
# for k in wire_groups:
# if self.is_horizontal_connection: # sort wires from top to bottom
# wire_groups[k] = sorted(wire_groups[k], key=lambda w:-w[0].y)
# else: # sort wires from left to right
# wire_groups[k] = sorted(wire_groups[k], key=lambda w:w[0].x)
# remove interpolation wires from wire groups
inkex.errormsg("num interp wires detected:{}".format(len(self.interpolation_wires)))
tmp_wires = [w for w in self.wires if w not in self.interpolation_wires]
self.wires = tmp_wires
return wire_groups
def arrange_wire_groups(self, wire_groups_dict):
'''
Before connecting wire groups, we first need to arrange them
from left -> right for horizontal connections and top -> bottom for
vertical connections
returns: list of keys in wire_groups dict sorted by this order
'''
key_wirepoint_pairs = [] # list of (key, first wire point in key group)
for key in wire_groups_dict.keys():
inkex.errormsg("what is wire group dict:{}".format(wire_groups_dict[key]))
wire1_points = [p for p in wire_groups_dict[key][0].path.end_points]
key_wirepoint_pairs.append((key, wire1_points[0]))
if self.is_horizontal_connection: # left to right
key_wirepoint_pairs = sorted(key_wirepoint_pairs, key=lambda p: p[1].x)
else:
key_wirepoint_pairs = sorted(key_wirepoint_pairs, key=lambda p: -p[1].y)
return [k for k,_ in key_wirepoint_pairs]
def connect_wires(self, wire_groups_dict, interp_wires=None, interp_dict=None, interp_start_indices=None):
start_points = sorted(list(wire_groups_dict.keys()))
start_points = self.arrange_wire_groups(wire_groups_dict)
wire_groups = [wire_groups_dict[k] for k in start_points]
wire_lens = [len(w) for w in wire_groups]
wire_indices = [0 for _ in range(len(wire_groups))] # starting indices
generated_combined_wires = []
generated_ids = []
while wire_indices != wire_lens:
joint_wire_points = []
interp_done = False # FIX THIS to better determine when to add interpolation wires!
@ -98,24 +149,26 @@ class CombineGridsWorker():
max_idx = wire_lens[wire_group_idx]
if curr_wire_idx != max_idx: # add the wire itself
current_wire = wire_groups[wire_group_idx][curr_wire_idx]
joint_wire_points.extend([[p.x, p.y] for p in current_wire])
joint_wire_points.extend([[p.x, p.y] for p in current_wire.path.end_points])
wire_indices[wire_group_idx] += 1
if interp_wires is not None and not interp_done: # add custom routes if inputted by user
if curr_wire_idx == 0: joint_wire_points.extend([[p.x,p.y] for p in interp_wires[0]])
elif curr_wire_idx == max_idx - 1: joint_wire_points.extend([[p.x,p.y] for p in interp_wires[1]])
else:
interp_points = self.add_interpolation_points(curr_wire_idx, interp_wires, interp_dict)
# check if interp points intersect with any others
#NEED ALL POINTS HERE!
joint_wire_points.extend(interp_points)
interp_done = True
generated_combined_wires.append(joint_wire_points)
joint_wire_points = ['{},{}'.format(p[0],p[1]) for p in joint_wire_points]
self.create_path(joint_wire_points, is_horizontal=self.is_horizontal_connection)
# can move this block before to prevent drawing of wires
elem = self.create_path(joint_wire_points, is_horizontal=self.is_horizontal_connection)
generated_ids.append(elem.get_id())
# generate new grouping of wires
self.wiredb_proxy.insert_new_wire_group(generated_ids)
# can move this block before to prevent drawing of wires
is_valid_routing = self.has_valid_interpolation_points(generated_combined_wires)
if not is_valid_routing:
inkex.errormsg("Please change your template routing wires.")
@ -213,14 +266,15 @@ class CombineGridsWorker():
return interp_start_indices
def connect_custom_wires(self, wire_groups_dict, interpolation_wires):
def connect_custom_wires(self, wire_groups_dict):
# how many wires are grouped together???
num_wires = len(wire_groups_dict[list(wire_groups_dict.keys())[0]])
interpolation_wires = [[p for p in w.path.end_points] for w in self.interpolation_wires]
interp_dict = self.generate_interpolation_points(interpolation_wires, num_wires)
# determine the wiregroups where the interpolation wires start
interp_start_indices = self.calculate_interp_wire_group(wire_groups_dict, interpolation_wires)
self.connect_wires(wire_groups_dict, interpolation_wires, interp_dict, interp_start_indices)
# interp_start_indices = self.calculate_interp_wire_group(wire_groups_dict, interpolation_wires)
self.connect_wires(wire_groups_dict, interpolation_wires, interp_dict, interp_start_indices=None)
def add_interpolation_points(self, wire_idx, interpolation_wires, interpolation_dict):
@ -240,18 +294,12 @@ class CombineGridsWorker():
def run(self):
for elem in self.svg.get_selected():
if type(elem) == PathElement: #connector
points = [p for p in elem.path.end_points]
# if len(points) == 4: # figure out differnt condition for this
# connector_bbox = elem.bounding_box()
# connector_pins.append(elem)
if len(points) > 2:
self.interpolation_wires.append(points)
else:
self.wires.append(points)
inkex.errormsg("\n\n\IDs:{}".format(elem.get_id()))
self.wires.append(elem)
wire_groups = self.group_wires(self.wires)
if len(self.interpolation_wires) == 0:
@ -267,13 +315,32 @@ class CombineGridsWorker():
if not same_length:
inkex.errormsg("interpolation wires have the same number of points")
return
# sort interpolation wires
interp_wire_points = []
interp_wire_dict = {}
for interp in self.interpolation_wires:
points = [p for p in interp.path.end_points]
interp_wire_points.append(points)
interp_wire_dict[interp] = points
inkex.errormsg('what is wire points:{}'.format(interp_wire_points))
if self.is_horizontal_connection:
self.interpolation_wires = sorted(self.interpolation_wires, key=lambda w:-w[0].y)
interp_wire_points = sorted(interp_wire_points, key=lambda w:-w[0].y)
else:
self.interpolation_wires = sorted(self.interpolation_wires, key=lambda w:w[0].x)
self.connect_custom_wires(wire_groups, self.interpolation_wires)
interp_wire_points = sorted(interp_wire_points, key=lambda w:w[0].x)
tmp_interp_wires = []
for p in interp_wire_points:
# find the wire that set of points corresponds to
for key in interp_wire_dict.keys():
if interp_wire_dict[key] == p:
tmp_interp_wires.append(key)
self.interpolation_wires = tmp_interp_wires
self.connect_custom_wires(wire_groups)
# remove old wires
old_wire_ids = [elem.get_id() for elem in self.svg.get_selected()]
# self.wiredb_proxy.delete_wire_groups_with_id(old_wire_ids)
for elem in self.svg.get_selected(): elem.getparent().remove(elem)
return
@ -295,8 +362,8 @@ class CombineGridsWorker():
# 'points': 'M 0,0 9,9 5,5'
}
etree.SubElement(self.svg.get_current_layer(), inkex.addNS('path','svg'), line_attribs)
elem = etree.SubElement(self.svg.get_current_layer(), inkex.addNS('path','svg'), line_attribs)
return elem
if __name__ == '__main__':

Wyświetl plik

@ -6,6 +6,8 @@ from inkex import Line, Rectangle, Path, Polyline
from lxml import etree
import pyembroidery
import math
from wiredb_proxy import WireDBProxy
MIN_GRID_SPACING = inkex.units.convert_unit(2.5, "mm")
@ -30,12 +32,7 @@ class CreateCustomGridEffect(inkex.Effect):
shape_points = None
for elem in self.svg.get_selected():
inkex.errormsg("wtf is elem:{},{}".format(elem, type(elem)))
shape_points = [p for p in elem.path.end_points]
# if type(elem) == Rectangle:
# for p in shape_points:
# p.x = inkex.units.convert_unit(p.x, "mm")
# p.y = inkex.units.convert_unit(p.y, "mm")
if len(shape_points) > 5:
inkex.errormsg("Please create a 4-sided shape.")
return
@ -50,7 +47,7 @@ class CreateCustomGridWorker():
self.num_vertical_wires = num_vertical_wires
self.svg = svg
self.upper_left, self.lower_left, self.upper_right, self.lower_right = self.compute_corners()
self.wiredb_proxy = WireDBProxy()
def compute_euclidean_distance(self, x1, y1, x2, y2):
return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2)
@ -87,8 +84,6 @@ class CreateCustomGridWorker():
def run(self):
# self.draw_corners()
horizontal_wire = None
vertical_wire = None
if self.num_horizontal_wires != 0:
# look at left and right side, take shorter one to compute spacing
left_side_distance = self.compute_euclidean_distance(self.upper_left.x, self.upper_left.y,
@ -107,8 +102,9 @@ class CreateCustomGridWorker():
number of wires or increase the size of the grid and try again.'''.format(MIN_GRID_SPACING, horizontal_wire_spacing))
return
horizontal_wire = self.lay_horizontal_wires(left_side_distance, right_side_distance)
horizontal_wire_ids = self.lay_horizontal_wires(left_side_distance, right_side_distance)
self.wiredb_proxy.insert_new_wire_group(horizontal_wire_ids)
if self.num_vertical_wires != 0:
top_side_distance = self.compute_euclidean_distance(self.upper_left.x, self.upper_left.y,
self.upper_right.x, self.upper_right.y)
@ -125,8 +121,8 @@ class CreateCustomGridWorker():
number of wires or increase the size of the grid and try again.'''.format(MIN_GRID_SPACING, vertical_wire_spacing))
return
vertical_wire = self.lay_vertical_wires(top_side_distance, bottom_side_distance)
vertical_wire_ids = self.lay_vertical_wires(top_side_distance, bottom_side_distance)
self.wiredb_proxy.insert_new_wire_group(vertical_wire_ids)
def segment_line(self, line, line_distance, num_points):
'''
@ -142,7 +138,7 @@ class CreateCustomGridWorker():
return x_t, y_t
segment_length = 1 / (num_points + 1)
for i in range(1 ,num_points+2): # adjust from 0 to n+1 bc we cant put in 0 to the parameterized line equation
for i in range(1 ,num_points+1): # adjust from 0 to n+1 bc we cant put in 0 to the parameterized line equation
x, y = parameterize_line(i * segment_length)
points.append([x,y])
return points
@ -151,8 +147,11 @@ class CreateCustomGridWorker():
left_line = [(self.upper_left.x, self.upper_left.y), (self.lower_left.x, self.lower_left.y)]
right_line = [(self.upper_right.x, self.upper_right.y), (self.lower_right.x, self.lower_right.y)]
left_side_points = self.segment_line(left_line, left_side_distance, self.num_horizontal_wires)
right_side_points = self.segment_line(right_line, right_side_distance, self.num_horizontal_wires)
self.lay_wire(left_side_points, right_side_points, is_horizontal=True)
inkex.errormsg("\n\n num points lr:{} {}".format(len(left_side_points), len(right_side_points)))
return self.lay_wire(left_side_points, right_side_points, is_horizontal=True)
def lay_vertical_wires(self, top_side_distance, bottom_side_distance):
@ -160,7 +159,7 @@ class CreateCustomGridWorker():
bottom_line = [(self.lower_left.x, self.lower_left.y), (self.lower_right.x, self.lower_right.y)]
top_side_points = self.segment_line(top_line, top_side_distance, self.num_vertical_wires)
bottom_side_points = self.segment_line(bottom_line, bottom_side_distance, self.num_vertical_wires)
self.lay_wire(top_side_points, bottom_side_points, is_horizontal=False)
return self.lay_wire(top_side_points, bottom_side_points, is_horizontal=False)
def lay_wire(self, wire1_points, wire2_points, is_horizontal):
@ -168,30 +167,34 @@ class CreateCustomGridWorker():
wire_count = 0
wire1_idx = 0
wire2_idx = 0
wire_ids = []
while wire1_idx < len(wire1_points) and wire2_idx < len(wire2_points):
if wire_count % 2 == 0:
if wire1_idx < len(wire1_points):
points.append('{},{}'.format(wire1_points[wire1_idx][0], wire1_points[wire1_idx][1]))
wire1_idx += 1
if wire2_idx < len(wire2_points):
points.append('{},{}'.format(wire2_points[wire2_idx][0], wire2_points[wire2_idx][1]))
wire2_idx += 1
else:
if wire2_idx < len(wire2_points):
points.append('{},{}'.format(wire2_points[wire2_idx][0], wire2_points[wire2_idx][1]))
wire2_idx += 1
if wire1_idx < len(wire1_points):
points.append('{},{}'.format(wire1_points[wire1_idx][0], wire1_points[wire1_idx][1]))
wire1_idx += 1
wire_count += 1
return self.create_path(points, is_horizontal)
# if wire_count % 2 == 0:
if wire1_idx < len(wire1_points):
points.append('{},{}'.format(wire1_points[wire1_idx][0], wire1_points[wire1_idx][1]))
wire1_idx += 1
if wire2_idx < len(wire2_points):
points.append('{},{}'.format(wire2_points[wire2_idx][0], wire2_points[wire2_idx][1]))
wire2_idx += 1
wire = self.create_path(points, is_horizontal)
wire_ids.append(wire.get_id())
points = []
# else:
# if wire2_idx < len(wire2_points):
# points.append('{},{}'.format(wire2_points[wire2_idx][0], wire2_points[wire2_idx][1]))
# wire2_idx += 1
# if wire1_idx < len(wire1_points):
# points.append('{},{}'.format(wire1_points[wire1_idx][0], wire1_points[wire1_idx][1]))
# wire1_idx += 1
inkex.errormsg("num wires generated:{} is horz:{}".format(len(wire_ids), is_horizontal))
return wire_ids
def create_path(self, points, is_horizontal):
'''
Creates a wire segment path given all of the points sequentially
'''
color = 'red' if is_horizontal else 'blue'
inkex.errormsg("point order:{}".format(points))
color = "red" if is_horizontal else "blue"
path_str = ' '.join(points)
path = inkex.Polyline(attrib={
'id': "wire_segment",
@ -201,9 +204,11 @@ class CreateCustomGridWorker():
line_attribs = {
'style' : "stroke: %s; stroke-width: 0.4; fill: none; stroke-dasharray:0.4,0.4" % color,
'd': str(path.get_path())
# 'points': 'M 0,0 9,9 5,5'
}
etree.SubElement(self.svg.get_current_layer(), inkex.addNS('path','svg'), line_attribs)
return path
elem = etree.SubElement(self.svg.get_current_layer(), inkex.addNS('path','svg'), line_attribs)
return elem
if __name__ == '__main__':
CreateCustomGridEffect().run()

Wyświetl plik

@ -0,0 +1,84 @@
import sqlite3
import inkex
'''
Proxy for interacting with database storing wire information
'''
class WireDBProxy:
def __init__(self):
self.wire_db = "wire_db"
self.init_wire_group_database()
def init_wire_group_database(self):
conn = sqlite3.connect(self.wire_db)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS wire_group_table
(wire_IDs text);''')
conn.commit()
conn.close()
def insert_new_wire_group(self, wire_ids):
'''
wire_ids: list of wireids (strings)
'''
id_string = ','.join(wire_ids)
conn = sqlite3.connect(self.wire_db)
cursor = conn.cursor()
cursor.execute('''
INSERT into wire_group_table VALUES (?);''', (id_string,))
conn.commit()
conn.close()
def retrieve_all_wire_groups(self):
conn = sqlite3.connect(self.wire_db)
cursor = conn.cursor()
result = cursor.execute('''SELECT * FROM wire_group_table''').fetchall()
groups = []
for g_tuple in result: groups.extend([wire_id.split(',') for wire_id in g_tuple])
conn.commit()
conn.close()
return groups
def retrieve_wire_group_with_id(self, wire_id):
conn = sqlite3.connect(self.wire_db)
cursor = conn.cursor()
result = cursor.execute('''
SELECT * FROM wire_group_table WHERE wire_IDs LIKE ('%' || ? || '%');''', (wire_id,)).fetchall()
groups = []
for g_tuple in result: groups.extend([wire_id.split(',') for wire_id in g_tuple])
inkex.errormsg("what are groups retrieved:{}".format(groups))
conn.commit()
conn.close()
return groups[0] if groups != [] else []
def delete_wire_groups_with_id(self, wire_ids):
'''
wire_ids: list of wire_ids to delete
'''
#get groupings from wire_ids
groups = []
allocated_ids = []
for w_id in wire_ids:
if w_id not in allocated_ids:
group = self.retrieve_wire_group_with_id(w_id)
allocated_ids.extend(group)
groups.append(group)
# delete groupings from table
conn = sqlite3.connect(self.wire_db)
cursor = conn.cursor()
for group in groups:
group_str = ','.join(group)
result = cursor.execute(''' DELETE FROM wire_group_table WHERE wire_IDs= ? ''', (group_str,)).fetchall()
groups = []
for g_tuple in result: groups.extend([wire_id.split(',') for wire_id in g_tuple])
inkex.errormsg("what are groups retrieved:{}".format(groups))
conn.commit()
conn.close()
return True