Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """triangulation"""
- class Point:
- def __init__(self, x, y, z):
- self._x, self._y, self._z = x, y, z
- def get_x(self): return self._x
- def get_y(self): return self._y
- def get_z(self): return self._z
- # TODO -------------------------------------------------------
- class Edge:
- def __init__(self, a, b):
- self._a, self._b = a, b
- self._t1 = self._t2 = None
- def get_a(self): return self._a
- def get_b(self): return self._b
- def get_t1(self): return self._t1
- def set_t1(self, t1): self._t1 = t1
- def get_t2(self): return self._t2
- def set_t2(self, t2): self._t2 = t2
- # TODO -------------------------------------------------------
- class Triangle:
- def __init__(self, a, b, c):
- self._a, self._b, self._c = a, b, c
- self._ab, self._bc, self._ac = Edge(a, b), Edge(b, c), Edge(a, c)
- if None != self._ab.get_t1(): self._ab.set_t1(self) #our triangle lies to the left from vector ab
- else: self._ab.set_t2(self)
- if None != self._bc.get_t1(): self._bc.set_t1(self)
- else: self._bc.set_t2(self)
- if None != self._ac.get_t2(): self._ac.set_t2(self) #and to the right from ac
- else: self._ac.set_t1(self)
- self._edges = [self._ab, self._bc, self._ac]
- self._abc = count_angle(self._ab, self._bc)
- self._bca = count_angle(self._bc, self._ac)
- self._cab = count_angle(self._ab, self._ac)
- if self._abc < self._bca and self._abc < self._cab: self._min_ang = self._abc
- elif self._cab < self._abc and self._cab < self._bca: self._min_ang = self._cab
- else: self._min_ang = self._bca
- self._color = 0
- def get_min_ang(self): return self._min_ang
- def get_edges(self): return self._edges
- # TODO -------------------------------------------------------
- class Band:
- def __init__(self):
- self._pts = []
- self._edges = []
- self._triangles = []
- def get_edges(self): return self._edges
- def set_edges(self, edges): self._edges = edges
- def get_pts(self): return self._pts
- def get_triangles(self): return self._triangles
- def set_triangles(self, triangles): self._triangles = triangles
- # TODO =======================================================
- def divide_into_bands(pts, band_num):
- band_list = []
- sorted_by_x = sorted(pts, key=lambda x: x.get_x())
- x_min = sorted_by_x[0]
- x_max = sorted_by_x[len(sorted_by_x)] + 0.001 # to engage last point
- band_width = (x_max - x_min) / band_num
- for i in range(1, band_num):
- x_from = x_min + (i - 1) * band_width
- x_to = x_min + i * band_width
- b = Band()
- b.get_pts().extend([x for x in pts if x_from <= x.get_x() < x_to])
- band_list.append(b)
- for i in range(1, band_num):
- b_prev = band_list[i - 1]
- b_curr = band_list[i]
- if len(b_curr.get_pts()) < 3:
- b_prev.get_pts().extend(b_curr.get_pts())
- band_list.remove(b_curr)
- band_num -= 1
- return band_list
- def triang_band(band):
- n = len(band.get_pts())
- sorted_by_y = sorted(band.get_pts(), key=lambda x: x.get_y(), reverse=True)
- triang_list = []
- first = Triangle(sorted_by_y[0], sorted_by_y[1], sorted_by_y[2])
- triang_list.append(first)
- for i in range(3, n):
- t = triang_list[len(triang_list) - 1] # prev triang
- p = band.get_pts()[i]
- t_new = object
- if intersect(Edge(t[0], t[2]), Edge(p, t[1])):
- t_new = Triangle(t[1], t[2], p)
- elif intersect(Edge(t[1], t[2]), Edge(p, t[0])):
- t_new = Triangle(t[0], t[2], p)
- else:
- tmp1 = Triangle(t[0], t[2], p)
- tmp2 = Triangle(t[1], t[2], p)
- if tmp1.get_min_ang() > tmp2.get_min_ang():
- t_new = tmp1
- else:
- t_new = tmp2
- triang_list.append(t_new)
- band.set_triangles(triang_list)
- return band
- def convex_band(band):
- """because fuck convexing"""
- pass
- def fill_triang_data(band):
- """fill triagnle data for every edge with DFS. then go edge by edge to make outline"""
- edges = []
- for t in band.get_triangles():
- edges.extend(t.get_edges())
- def get_outlines(band):
- def find_edges_by_point(edges, p):
- res = []
- for e in edges:
- if e.get_a() is p or e.get_b() is p:
- res.append(e)
- return res
- def filter_edges_below_point(edges, p):
- """find edges that lay below point p"""
- res = []
- for e in edges:
- if e.get_a() is p and p.get_y() > e.get_b().get_y():
- res.append(e)
- elif e.get_b() is p and p.get_y() > e.get_a().get_y():
- res.append(e)
- return res
- def find_leftmost_edge(edges, p):
- """find leftmost edge by leftmost point among those which below point p"""
- leftmost_edge = object
- xmin = 999
- for e in edges:
- if e.get_a() is not p:
- if e.get_a().get_x() < xmin:
- xmin = e.get_a().get_x()
- leftmost_edge = e
- elif e.get_b() is not p:
- if e.get_b().get_x() < xmin:
- xmin = e.get_b().get_x()
- leftmost_edge = e
- return leftmost_edge
- def find_rightmost_edge(edges, p):
- rightmost_edge = object
- xmax = -999
- for e in edges:
- if e.get_a() is not p:
- if e.get_a().get_x() > xmax:
- xmax = e.get_a().get_x()
- rightmost_edge = e
- elif e.get_b() is not p:
- if e.get_b().get_x() > xmax:
- xmax = e.get_b().get_x()
- rightmost_edge = e
- return rightmost_edge
- sorted_edges = sorted(band.get_edges(), key=lambda x: x.get_a().get_y())
- sorted_pts = sorted(band.get_pts(), key=lambda x: x.get_y())
- top = sorted_pts[0]
- bot = sorted_pts[len(sorted_pts) - 1]
- left_outline = []
- while top is not bot:
- es = find_edges_by_point(sorted_edges, top)
- es2 = filter_edges_below_point(es, top)
- leftmost_e = find_leftmost_edge(es2, top)
- left_outline.append(leftmost_e)
- if leftmost_e.get_a() is top:
- top = leftmost_e.get_b()
- elif leftmost_e.get_b() is top:
- top = leftmost_e.get_a()
- right_outline = []
- while top is not bot:
- es = find_edges_by_point(sorted_edges, top)
- es2 = filter_edges_below_point(es, top)
- rightmost_e = find_rightmost_edge(es2, top)
- right_outline.append(rightmost_e)
- if rightmost_e.get_a() is top:
- top = rightmost_e.get_b()
- elif rightmost_e.get_b() is top:
- top = rightmost_e.get_a()
- return left_outline, right_outline
- def merge_bands(band_left, band_right):
- _t, contour1 = get_outlines(band_left)
- contour2, _t = get_outlines(band_right)
- #considering only 2 nearest outlines:
- #right outline of left band
- sorted_left_edges = sorted(contour1, key=lambda x: x.get_a().get_y() + x.get_b().get_y(), reverse=True)
- t1 = retrieve_points(contour1)
- sorted_left_points = sorted(t1, key=lambda x: x.get_y(), reverse=True)
- #and left outline of right band
- sorted_right_edges = sorted(contour2, key=lambda x: x.get_a().get_y() + x.get_b().get_y(), reverse=True)
- t2 = retrieve_points(contour2)
- sorted_right_points = sorted(t2, key=lambda x: x.get_y(), reverse=True)
- starting_point = highest_point(sorted_left_edges[0], sorted_right_edges[0])
- # make edge list representing right outline of left band
- left_sorted_by_y = sorted(band1.get_pts(), key=lambda x: x.get_y(), reverse=True)
- p_top1 = left_sorted_by_y[0]
- left_outline = []
- lower_by_y = sorted(band1.get_pts(), key=lambda x: x.get_y() < left_sorted_by_y[0])
- # -//- left outline of right band
- right_sorted_by_y = sorted(band2.get_pts(), key=lambda x: x.get_y(), reverse=True)
- p_top2 = right_sorted_by_y[0]
- p0, p1 = object, object
- if p_top1 > p_top2:
- p0 = p_top1
- p1 = p_top2
- else:
- p0 = p_top2
- p1 = p_top1
- pass
- def count_angle(e1, e2):
- return 60
- def intersect(e1, e2):
- return True
- def highest_point(e1, e2):
- max_e1, max_e2 = object, object
- if e1.get_a().get_y() > e1.get_b().get_y(): max_e1 = e1.get_a()
- else: max_e1 = e1.get_b()
- if e2.get_a().get_y() > e2.get_b().get_y(): max_e2 = e2.get_a()
- else: max_e2 = e2.get_b()
- if max_e1 > max_e2: return max_e1
- else: return max_e2
- def retrieve_points(edges):
- res = set()
- for e in edges:
- res.add(e.get_a())
- res.add(e.get_b())
- return res
- def triang():
- points = []
- band_num = 3
- def main():
- pass
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment