def build_tmap(): """Построение трапецоидной карты из примера""" tmap = TrapezoidMap() f = open("tests/example.off", "r") f.readline() line = f.readline() n = int(line[0:2]) m = int(line[5:7]) point_list = [] i = 0 while i < n: pair = f.readline().split(' ') point_list.append([int(pair[0]), int(pair[1])]) i += 1 i = 0 while i < m: pair = f.readline().split(' ') p1 = int(pair[0]) - 1 p2 = int(pair[1]) - 1 p = Point(point_list[p1][0], point_list[p1][1]) q = Point(point_list[p2][0], point_list[p2][1]) if q < p: p, q = q, p solution.insert(tmap, Segment(p, q)) i += 1 f.close() return tmap
def simple_insert_test(insert): for i in range(7): with open('tests/' + str(i)) as f: n = int(next(f)) answer = TrapezoidMap() check = TrapezoidMap() segment_list = [] for j in range(n): px, py, qx, qy = [int(x) for x in next(f).split()] s = Segment(Point(px, py), Point(qx, qy)) segment_list.append(s) solution.insert(answer, s) insert(check, s) if not tmap_equal(answer, check): return False if i in [2, 6]: for j in range(50): answer = TrapezoidMap() check = TrapezoidMap() for pos in np.random.permutation(n): solution.insert(answer, segment_list[pos]) insert(check, segment_list[pos]) if not tmap_equal(answer, check): return False return True
def get_neighbour(self, point): """ возвращает пиксель, смежный по той грани, которой принадлежит точка :param point: экземпляр Point :return: Pixel смежный пиксель """ res = average(eps, self.center) new_eps = res[0] new_self = res[1] if self.is_on_top(point): return get_pixel( Point(int(new_self.x), int(new_self.y + new_eps), int(new_self.z), homogeneous=True)) if self.is_on_bottom(point): return get_pixel( Point(int(new_self.x), int(new_self.y - new_eps), int(new_self.z), homogeneous=True)) else: return None
def read_slabs(path): fin = open(path, 'r') xx = [e for e in map(int, fin.readline().rstrip().split())] yy = [e for e in map(int, fin.readline().rstrip().split())] n = int(fin.readline().rstrip()) edges = list() for i in range(n): x1, y1, x2, y2 = map(int, fin.readline().rstrip().split()) edges.append([Point(x1, y1), Point(x2, y2)]) n = int(fin.readline().rstrip()) vertices = [Vertex() for i in range(n)] for i in range(n): edge, left, right, next2, direction, version = fin.readline( ).rstrip().split() edge, left, right, next2, version = int(edge), int(left), int( right), int(next2), int(version) vertices[i].version = version vertices[i].edge = edges[edge - 1] if left != -1: vertices[i].left = vertices[left] if right != -1: vertices[i].right = vertices[right] if next2 != -1: vertices[i].next = vertices[next2] vertices[i].is_left = direction == 'l' roots = [ vertices[e] if e != -1 else None for e in map(int, fin.readline().rstrip().split()) ] fin.close() return Slabs(xx, yy, edges, vertices, roots)
def intersection_test(func): tmap = build_tmap() correct = True with open('tests/example_segments.txt') as f: n = int(next(f)) for i in range(n): px, py, qx, qy = [int(x) for x in next(f).split()] s = Segment(Point(px, py), Point(qx, qy)) first_tr = solution.localize(tmap, s) answer = solution.intersect_segment(s, first_tr) check = func(s, first_tr) if type(check) == type(answer): temp = [] item = next(check, None) while item is not None: temp.append(item) item = next(check, None) check = temp next_tr = next(answer, None) pos = 0 while next_tr is not None: if pos >= len(check): correct = False break tr = check[pos] if not data_equal(tr, next_tr): correct = False break pos += 1 next_tr = next(answer, None) if pos != len(check): correct = False break return correct
def read_slab(file): fin = open(file, "r") edges = list() for line in fin: x1, y1, x2, y2 = map(int, line.rstrip().split()) edges.append([Point(x1, y1), Point(x2, y2)]) fin.close() return Slab(edges)
def intersects(self, other): """ пересечение отрезка с другим отрезком :param other: экземпляр Segment :return: Point точка пересечения или None, если пересечения нет """ a, b = normalize(self.start), normalize(self.end) c, d = normalize(other.start), normalize(other.end) if (a == c) and (b == d): return None acd, bcd = turn(a, c, d), turn(b, c, d) cab, dab = turn(c, a, b), turn(d, a, b) do_intersect = False if acd == bcd == cab == dab == 0: do_intersect = (a <= c <= b or a <= d <= b or c <= a <= d or c <= b <= d) else: do_intersect = acd != bcd and cab != dab if do_intersect: cross = lambda a, b: np.cross([a.coord], [b.coord]) prod = np.cross(cross(a, b), cross(c, d))[0] if (prod[0] == 0 and prod[1] == 0 and prod[2] == 0): return max(b, d) return normalize(Point(prod, homogeneous=True)) return None
def se(self): res = average(eps / 2, self.center) new_eps = res[0] new_self = res[1] return Point(int(new_self.x + new_eps), int(new_self.y - new_eps), int(new_self.z), homogeneous=True)
def non_crossing_insert_test(insert): if not simple_insert_test(insert): print('Простые тесты не пройдены') return False with open('tests/7') as f: n = int(next(f)) segment_list = [] for j in range(n): px, py, qx, qy = [int(x) for x in next(f).split()] segment_list.append(Segment(Point(px, py), Point(qx, qy))) for j in range(10): answer = TrapezoidMap() check = TrapezoidMap() for pos in np.random.permutation(n): solution.insert(answer, segment_list[pos]) insert(check, segment_list[pos]) if not tmap_equal(answer, check): return False return True
def setUp(self): points = [(0, 0), (-1, 3), (3, 0), (2, 3), (0, 6), (4, 6), (7, 4)] points = [Point(*args) for args in points] points.append(Point.infinity(2)) points = [Vertex(p, None) for p in points] faces = [[0, 2, 1], [1, 2, 3], [1, 3, 4], [3, 5, 4], [3, 6, 5], [3, 2, 6], [0, 1, 7], [1, 4, 7], [4, 5, 7], [5, 6, 7], [6, 2, 7], [2, 0, 7]] connections = [0, 0, 0, 1, 2, 3, 4, 6] faces = [ Face([points[i], points[j], points[k]], None) for i, j, k in faces ] for i, v in enumerate(points): v.face = faces[connections[i]] neighbours = [[1, 6, 11], [5, 2, 0], [3, 7, 1], [8, 2, 4], [9, 3, 5], [10, 4, 1], [7, 11, 0], [8, 6, 2], [9, 7, 3], [10, 8, 4], [11, 9, 5], [6, 10, 0]] for f, (i, j, k) in zip(faces, neighbours): f.neighbours = [faces[i], faces[j], faces[k]] self.vertices = points self.faces = faces
def add_edge(from_h, to_h): # новое ребро tmp = Point(int(from_h.next.origin.x), int(from_h.next.origin.y)) h = Hedge(tmp) tmp = Point(int(to_h.origin.x), int(to_h.origin.y)) h.twin = Hedge(tmp) h.twin.twin = h # from -> new from_h.next = h h.prev = from_h from_h.twin.prev = h.twin h.twin.next = from_h.twin # new -> to h.next = to_h to_h.prev = h h.twin.prev = to_h.twin to_h.twin.prev = h.twin return h
def get_right_neighbour(self): """ возвращает пиксель, смежный по правой границе :return: экземпляр Pixel """ res = average(eps, self.center) new_eps = res[0] new_self = res[1] return get_pixel( Point(int(new_self.x + new_eps), int(new_self.y), int(new_self.z), homogeneous=True))
def normalize(smth): """ возвращает точку с упрощенными однородными координатами :param smth: экземпляр Point :return: экземпляр Point """ m = smart_gcd(smth.x, smart_gcd(smth.y, smth.z)) q = 1 if (smth.z <= 0): q = 1 return Point(int(q * (smth.x // m)), int(q * (smth.y // m)), int(q * (smth.z // m)), homogeneous=True)
def rounded(point): """ округляет точку до центра ближайшего пикселя :param x: экземпляр Point :return: Point, являющийся центром пикселя, которому принадлежит x """ res = average(eps, point) new_eps = res[0] new_point = res[1] return normalize( Point(int(halfround(new_point.x, new_eps)), int(halfround(new_point.y, new_eps)), int(new_point.z), homogeneous=True))
def average(ceps, point): """ приводит данную точность и точку на "один уровень" однородных координат :param ceps: float :param point: экземпляр Point :return: (int, Point) """ zeps = 1 while (((zeps * ceps) % 1 != 0)): zeps *= 10 m = gcd(point.z, zeps) new_eps = int(zeps * ceps * (point.z // m)) new_point = Point(int(point.x * (zeps // m)), int(point.y * (zeps // m)), int(point.z * (zeps // m)), homogeneous=True) return (new_eps, new_point)
def point_inside(pixel, segment): """ возвращает точку, принадлежащую segment, находящуюся внутри pixel :param pixel: экземпляр Pixel :param segment: экземпляр Segment :return: экземпляр Point """ tmp = [] cnt = 0 for q in segment.intersections(pixel): if (q is not None): tmp.append(q) cnt += 1 if cnt == 0: return None if cnt >= 2: temp = tmp[0] + tmp[1] return Point(int(temp.x), int(temp.y), int(temp.z * 2), homogeneous=True) return tmp[0]
def testIterator(self): right_order = [0, 1, 5, 4, 9] for i, ver in enumerate(walk_along(self.vertices[0], Point(7, 7))): self.assertTrue(ver is self.faces[right_order[i]])
def test_comparator(comp): edges = [[Point(0, 0), Point(1, 0)], [Point(0, 1), Point(1, 1)], [Point(0, 0), Point(1, 0)], [Point(0, 0), Point(1, 1)], [Point(0, 0), Point(1, 0)], [Point(0, 1), Point(1, 0)], [Point(0, 0), Point(1, 0)], [Point(-4, 1), Point(8, 9)], [Point(-5, -1), Point(1, 9)], [Point(0, 0), Point(1, 0)], [Point(0, 0), Point(1, 0)], [Point(0, 9), Point(4, -1)]] for i in range(0, len(edges), 2): print("Running test #", (i // 2) + 1) if comp(edges[i], edges[i + 1]) != correct_comparator( edges[i], edges[i + 1]): print("Failure") return print("Passed") print("Passed all tests")
from cg import Point, turn import itertools as itertools triangles = [ [Point(-2, 2), Point(3, 1), Point(-2, -4)], [Point(1, 3), Point(0, 0), Point(5, 2)], [Point(-5, 4), Point(5, 4), Point(0, -12)], [Point(-3, 1), Point(0, 2), Point(-3, 3)], [Point(-4, -1), Point(-1, -1), Point(-1, -2)], [Point(4, 5), Point(9, 5), Point(6, 2)], [Point(4, 3), Point(6, 6), Point(9, 3)] ] def overlap(a, b): if a[0] <= b[0] and b[1] <= a[1]: return True if a[0] <= b[0] and b[0] <= a[1]: return True return False def intersect_segments(a, b): if turn(a[0], a[1], b[0]) * turn(a[0], a[1], b[1]) == 1: return False if turn(b[0], b[1], a[0]) * turn(b[0], b[1], a[1]) == 1: return False x1, y1 = a[0].coord[0], a[0].coord[1] x2, y2 = a[1].coord[0], a[1].coord[1] x3, y3 = b[0].coord[0], b[0].coord[1] x4, y4 = b[1].coord[0], b[1].coord[1]
from cg import Point, Vertex, Face points = [(0, 13), (3, 11), (7, 13), (8, 11), (10, 19), (10, 15), (13, 11), (16, 14), (14, 11), (15, 7)] points = [Point.infinity(2)] + [Point(*args) for args in points] points = [Vertex(p, None) for p in points] for i, v in enumerate(points): v.name = i points[0].name = "infinity" faces = [ [2, 3, 1], [3, 5, 1], [6, 5, 3], [4, 6, 3], [4, 3, 2], [10, 4, 2], [7, 6, 4], [8, 5, 6], [7, 8, 6], [10, 7, 4], [9, 8, 7], [10, 9, 7], [8, 9, 10], [1, 5, 0], #13 [5, 8, 0], #14 [8, 10, 0], #15 [10, 2, 0], #16 [2, 1, 0] #17 ]