def test_incomplete_table(self): """ Table with missing bottom border: point = * link = - or | missing point = . 9 *--*---*--* | | 8 *--*---*--* | | | | 0 . * * . 0 3 5 8 """ points = [ Point((0, 8)), Point((0, 9)), Point((3, 0)), Point((3, 8)), Point((3, 9)), Point((5, 0)), Point((5, 8)), Point((5, 9)), Point((8, 8)), Point((8, 9)) ] network = LTNetwork() for point in points: network.add_point(point) network.add_link(points[0], points[3]) network.add_link(points[1], points[4]) network.add_link(points[2], points[3]) network.add_link(points[3], points[4]) network.add_link(points[3], points[6]) network.add_link(points[4], points[7]) network.add_link(points[5], points[6]) network.add_link(points[6], points[7]) network.add_link(points[6], points[8]) network.add_link(points[7], points[9]) self.assertEqual(10, len(network.links_list())) self.assertEqual(10, len(network.points)) network.close_network() self.assertEqual(12, len(network.points)) self.assertEqual(10 + 7, len(network.links_list())) table = Table(network) self.assertEqual(6, len(table.cells))
def _align_nodes(self): """ Makes the links horizontal/vertical by aligning nodes. """ # make an histogram of the most common x and y values raw_x_values = defaultdict(int) raw_y_values = defaultdict(int) for point in self: raw_x_values[point.x] += 1 raw_y_values[point.y] += 1 # stores which values to replace (remove close values) replace_x = {} for x in raw_x_values: for x_prime in raw_x_values: if x != x_prime and abs(x - x_prime) < 5: if raw_x_values[x_prime] > raw_x_values[x]: replace_x[x] = x_prime elif raw_x_values[x_prime] == raw_x_values[x]: # in case they are the same, we must ensure # we don't substitute both by each other. if x > x_prime: replace_x[x] = x_prime else: replace_x[x_prime] = x else: replace_x[x_prime] = x replace_y = {} for y in raw_y_values: for y_prime in raw_y_values: if y != y_prime and abs(y - y_prime) < 5: if raw_y_values[y_prime] > raw_y_values[y]: replace_y[y] = y_prime elif raw_y_values[y_prime] == raw_y_values[y]: # in case they are the same, we must ensure # we don't substitute both by each other. if y > y_prime: replace_y[y] = y_prime else: replace_y[y_prime] = y else: replace_y[y_prime] = y for point in list(self)[:]: if point.x in replace_x: self.replace(point, Point((replace_x[point.x], point.y))) for point in list(self)[:]: if point.y in replace_y: self.replace(point, Point((point.x, replace_y[point.y])))
def _fix_intersections(self): """ Computes all intersections of links and creates points in the intersections, subdividing the links accordingly. """ links = self.links_list() vertical_links = [link for link in links if link[0].x == link[1].x] horizontal_links = [link for link in links if link[0].y == link[1].y] assert(len(links) == len(vertical_links) + len(horizontal_links)) v_links_to_subdivide = defaultdict(set) h_links_to_subdivide = defaultdict(set) for link in vertical_links: for link_prime in horizontal_links: if intersect(link[0], link[1], link_prime[0], link_prime[1]): point = Point((link[0].x, link_prime[0].y)) v_links_to_subdivide[link].add(point) h_links_to_subdivide[link_prime].add(point) for link in h_links_to_subdivide: points = sorted(h_links_to_subdivide[link], key=lambda p: p.x) self._subdivide(link[0], link[1], points) for link in v_links_to_subdivide: points = sorted(v_links_to_subdivide[link], key=lambda p: p.y) self._subdivide(link[0], link[1], points)
def close_network(self): """ Adds possible missing corners and border links to close the network. """ rows_borders = sorted(list(set(point.y for point in self))) columns_borders = sorted(list(set(point.x for point in self))) x0 = columns_borders[0] y0 = rows_borders[0] x1 = columns_borders[-1] y1 = rows_borders[-1] # add possible missing corners for corner in ((x0, y0), (x0, y1), (x1, y1), (x1, y0)): self.add_point(Point(corner)) # add possible missing bottom and top borders for row in (rows_borders[0], rows_borders[-1]): points = sorted([point for point in self if point.y == row], key=lambda p: p.x) for i, point in enumerate(points): if i == 0: continue self.add_link(points[i - 1], point) # add possible missing left and right borders for column in (columns_borders[0], columns_borders[-1]): points = sorted([point for point in self if point.x == column], key=lambda p: p.y) for i, point in enumerate(points): if i == 0: continue self.add_link(points[i - 1], point)
def test_missing_intersection_points(self): points = [Point((0, 0)), Point((2, 0)), Point((1, -1)), Point((1, 1))] network = LTNetwork() for point in points: network.add_point(point) network.add_link(points[0], points[1]) network.add_link(points[2], points[3]) network._fix_intersections() self.assertTrue(Point((1, 0)) in network) self.assertEqual(network.links[Point((1, 0))], set(points))
def test_missing_intersection_links(self): points = [ Point((0, 0)), Point((2, 0)), Point((1, -1)), Point((1, 1)), Point((1, 0)) ] network = LTNetwork() for point in points: network.add_point(point) network.add_link(points[0], points[1]) network.add_link(points[2], points[3]) network._fix_missing_links() expected = points[:-1] self.assertEqual(network.links[Point((1, 0))], set(expected))
def test_a(self): network = UndirectedNetwork() points = {Point((0, 0)), Point((1, 0)), Point((0, 1)), Point((1, 1))} for point in points: network.add_point(point) network.add_link(Point((0, 0)), Point((0, 1))) network.add_link(Point((0, 0)), Point((1, 0))) network.add_link(Point((0, 1)), Point((1, 1))) network.add_link(Point((1, 0)), Point((1, 1))) self.assertEqual(4, len(network)) self.assertEqual(4, len(network.links_list())) network.remove_point(Point((0, 0))) self.assertEqual(3, len(network)) self.assertEqual(2, len(network.links_list())) network.remove_link(Point((0, 1)), Point((1, 1))) self.assertEqual(3, len(network)) self.assertEqual(1, len(network.links_list()))
def test_a(self): network = LTNetwork() points = {Point((0, 0)), Point((1, 0)), Point((0, 1)), Point((1, 1))} for point in points: network.add_point(point) network.add_link(Point((0, 0)), Point((0, 1))) network.add_link(Point((0, 0)), Point((1, 0))) network.add_link(Point((0, 1)), Point((1, 1))) network.add_link(Point((1, 0)), Point((1, 1))) table = Table(network) self.assertEqual('<table>\n<tr>\n<td></td>\n</tr>\n</table>', table.as_html())
def test_non_squared_cells(self): """ Table with non-squared cells point = * link = - or | 9 *--*---* | | | 1 *--*---* | | 0 *------* 0 1 9 """ network = LTNetwork() points = { Point((0, 0)), Point((9, 0)), Point((0, 9)), Point((9, 9)), Point((0, 1)), Point((9, 1)), Point((1, 1)), Point((1, 9)) } for point in points: network.add_point(point) network.add_link(Point((0, 0)), Point((0, 1))) network.add_link(Point((0, 0)), Point((9, 0))) network.add_link(Point((0, 1)), Point((1, 1))) network.add_link(Point((0, 1)), Point((0, 9))) network.add_link(Point((0, 9)), Point((1, 9))) network.add_link(Point((9, 0)), Point((9, 1))) network.add_link(Point((1, 1)), Point((1, 9))) network.add_link(Point((1, 1)), Point((9, 1))) network.add_link(Point((1, 9)), Point((9, 9))) network.add_link(Point((9, 1)), Point((9, 9))) self.assertEqual(10, len(network.links_list())) network.add_collinear_links() self.assertEqual(10 + 4, len(network.links_list())) table = Table(network) self.assertEqual(3, len(table.cells)) expected = '<table>\n' \ '<tr>\n<td></td>\n<td></td>\n</tr>\n' \ '<tr>\n<td colspan="2"></td>\n</tr>\n' \ '</table>' self.assertEqual(expected, table.as_html())