def draw_cutter(self, event): color = self.frame.colors['cutter'] event_x, event_y = cfg.int_n(event.x), cfg.int_n(event.y) if not self.start: self.delete('cutter') self.delete('result') self.frame.cutter = [] self.draw_line(event_x, event_y, event_x + 1, event_y, self.color, 'cutter') self.start = cfg.Point(event_x, event_y, color) self.old = cfg.Point(event_x, event_y, color) else: try: if event.state in cfg.Ctrl: if event_x == self.old.x: m = 0 else: m = abs(event_y - self.old.y) / abs(event_x - self.old.x) if m < math.tan(math.pi / 4): new_point = cfg.Point(event_x, self.old.y, color) else: new_point = cfg.Point(self.old.x, event_y, color) else: raise AttributeError except AttributeError: new_point = cfg.Point(event_x, event_y, color) self.draw_line(self.old.x, self.old.y, new_point.x, new_point.y, color, 'cutter') self.frame.cutter.append([self.old, new_point]) self.old = new_point
def bresenham_int(canvas, start, finish): x1, y1, x2, y2 = start.x, start.y, finish.x, finish.y dx, dy = x2 - x1, y2 - y1 sx, sy = cfg.sign(dx), cfg.sign(dy) dx, dy = abs(dx), abs(dy) if dx > dy: exchange = 0 else: dx, dy = dy, dx exchange = 1 e = dy + dy - dx x, y = cfg.int_n(x1), cfg.int_n(y1) color = start.color for _ in range(int(dx)): canvas.set_pixel(cfg.Point(x, y, color)) if e >= 0: if exchange == 1: x += sx else: y += sy e -= (dx + dx) if e < 0: if exchange == 1: y += sy else: x += sx e += (dy + dy)
def draw_line(self, event): event_x, event_y = cfg.int_n(event.x), cfg.int_n(event.y) if not self.first: # self.create_line(event_x, event_y, event_x + 1, event_y, fill=self.color) self.set_pixel(cfg.Point(event_x, event_y, self.color)) self.first = cfg.Point(event_x, event_y, self.color) self.old = cfg.Point(event_x, event_y, self.color) else: try: if event.state in cfg.Ctrl: if event_x == self.old.x: m = 0 else: m = abs(event_y - self.old.y) / abs(event_x - self.old.x) if m < math.tan(math.pi / 4): new_point = cfg.Point(event_x, self.old.y, self.color) else: new_point = cfg.Point(self.old.x, event_y, self.color) else: raise AttributeError except AttributeError: new_point = cfg.Point(event_x, event_y, self.color) self.create_line(self.old.x, self.old.y, new_point.x, new_point.y, fill=self.color) # alg.bresenham_int(self, self.old, new_point) self.edges.append((self.old, new_point)) self.old = new_point
def draw_cutter(self, event): color = self.frame.colors['cutter'] if not self.cutter_1: self.cutter_1.set(cfg.int_n(event.x), cfg.int_n(event.y), color) else: self.cutter_2.set(cfg.int_n(event.x), cfg.int_n(event.y), color) self.delete('cutter') self.delete('result') self.draw_rectangle(self.cutter_1, self.cutter_2, color, tag='cutter') self.cutter_1.clear() self.cutter_2.clear()
def create_section(self): coors = self.section_coors.get().split() self.section_coors.delete(0, 'end') try: x1, y1 = cfg.int_n(float(coors[0])), cfg.int_n(float(coors[1])) x2, y2 = cfg.int_n(float(coors[2])), cfg.int_n(float(coors[3])) self.canvas.draw_line(x1, y1, x2, y2, self.colors['section']) self.section.append([ cfg.Point(x1, y1, self.colors['section']), cfg.Point(x2, y2, self.colors['section']) ]) except IndexError: mb.showerror('Ошибка', 'Должно быть введено 4 координаты') except ValueError: mb.showerror( 'Ошибка', 'Каждая координата должна быть числом, введенным через пробел')
def create_cutter(self): coors = self.cutter_coors.get().split() self.cutter_coors.delete(0, 'end') try: x1, y1 = cfg.int_n(float(coors[0])), cfg.int_n(float(coors[1])) x2, y2 = cfg.int_n(float(coors[2])), cfg.int_n(float(coors[3])) self.canvas.delete('cutter') self.canvas.delete('result') self.canvas.draw_rectangle(cfg.Point(x1, y1), cfg.Point(x2, y2), self.colors['cutter'], 'cutter') # self.canvas.create_rectangle(x1, y1, x2, y2, fill='', outline=self.colors['cutter'], tag='cutter') # self.cutter = (cfg.Point(x1, y1, self.colors['cutter']), cfg.Point(x2, y2, self.colors['cutter'])) except IndexError: mb.showerror('Ошибка', 'Должно быть введено 4 координаты') except ValueError: mb.showerror( 'Ошибка', 'Каждая координата должна быть числом, введенным через пробел')
def draw_section(self, event): event_x, event_y = cfg.int_n(event.x), cfg.int_n(event.y) color = self.frame.colors['section'] if not self.section_1: self.section_1.set(event_x, event_y, color) else: if event.state not in cfg.Ctrl: self.section_2.set(event_x, event_y, color) else: if event_x == self.section_1.x: m = 0 else: m = abs(event_y - self.section_1.y) / abs(event_x - self.section_1.x) if m < math.tan(math.pi / 4): self.section_2.set(event_x, self.section_1.y, color) else: self.section_2.set(self.section_1.x, event_y, color) self.draw_line(self.section_1.x, self.section_1.y, self.section_2.x, self.section_2.y, color) self.frame.section.append([self.section_1, self.section_2]) self.section_1 = cfg.Point(exist=False) self.section_2 = cfg.Point(exist=False)
def draw_line(self, event): event_x, event_y = cfg.int_n(event.x), cfg.int_n(event.y) if isinstance(event, tk.Event) and event.state == cfg.Shift: self.delete('seed') self.seed = cfg.Point(event_x, event_y, self.color) self.create_oval(event_x - 3, event_y - 3, event_x + 3, event_y + 3, fill='red', tag='seed') elif not self.first: # self.create_line(event_x, event_y, event_x + 1, event_y, fill=self.color) self.set_pixel(cfg.Point(event_x, event_y, self.color)) self.first = cfg.Point(event_x, event_y, self.color) self.old = cfg.Point(event_x, event_y, self.color) else: try: if event.state in cfg.Ctrl: if event_x == self.old.x: m = 0 else: m = abs(event_y - self.old.y) / abs(event_x - self.old.x) if m < math.tan(math.pi / 4): new_point = cfg.Point(event_x, self.old.y, self.color) else: new_point = cfg.Point(self.old.x, event_y, self.color) else: raise AttributeError except AttributeError: new_point = cfg.Point(event_x, event_y, self.color) # self.create_line(self.old.x, self.old.y, new_point.x, new_point.y, fill=self.color) alg.bresenham_int(self, self.old, new_point) self.edges.append((self.old, new_point)) self.old = new_point
def algorithm_partition(canvas, delay=False): if not canvas.edges: return mb.showerror( 'Ошибка!', 'Невозможно выполнить действие, так как отсутствует область для закрашивания' ) start = time.time() partition = find_partition(canvas.edges) for edge in canvas.edges: x1, y1 = edge[0].x, edge[0].y x2, y2 = edge[1].x, edge[1].y if y1 != y2: if y1 > y2: x1, x2 = x2, x1 y1, y2 = y2, y1 dx = (x2 - x1) / abs(y2 - y1) x_start = x1 for y_cur in range(y1, y2): x_cur = cfg.int_n(x_start) if x_cur < partition: while x_cur < partition: canvas.inverse_pixel(x_cur, y_cur, canvas.color) x_cur += 1 else: while x_cur >= partition: canvas.inverse_pixel(x_cur, y_cur, canvas.color) x_cur -= 1 x_start += dx if delay: time.sleep(0.05) canvas.update() canvas.update() finish = time.time() - start return finish
def cut_simple(canvas, cutter, sections): color = canvas.frame.colors['result'] canvas.create_rectangle(cutter['left'], cutter['bottom'], cutter['right'], cutter['top'], fill='white', tag='result') start = time.time() for section in sections: s = [] for point in section: s.append(set_codes(point, cutter)) if s[0] == 0 and s[1] == 0: canvas.draw_line(section[0].x, section[0].y, section[1].x, section[1].y, color, 'result') continue if s[0] & s[1]: continue cur_index = 0 result = [] if s[0] == 0: cur_index = 1 result.append([section[0].x, section[0].y]) elif s[1] == 0: result.append([section[1].x, section[1].y]) cur_index = 1 section.reverse() s.reverse() while cur_index < 2: if section[0].x == section[1].x: result.append(find_vertical(section, cur_index, cutter)) cur_index += 1 continue m = (section[1].y - section[0].y) / (section[1].x - section[0].x) if s[cur_index] & MASK_LEFT: y = cfg.int_n(m * (cutter['left'] - section[cur_index].x) + section[cur_index].y) if cutter['top'] >= y >= cutter['bottom']: result.append([cutter['left'], y]) cur_index += 1 continue elif s[cur_index] & MASK_RIGHT: y = cfg.int_n(m * (cutter['right'] - section[cur_index].x) + section[cur_index].y) if cutter['top'] >= y >= cutter['bottom']: result.append([cutter['right'], y]) cur_index += 1 continue if m == 0: cur_index += 1 continue if s[cur_index] & MASK_TOP: x = cfg.int_n((cutter['top'] - section[cur_index].y) / m + section[cur_index].x) if cutter['right'] >= x >= cutter['left']: result.append([x, cutter['top']]) cur_index += 1 continue elif s[cur_index] & MASK_BOTTOM: x = cfg.int_n((cutter['bottom'] - section[cur_index].y) / m + section[cur_index].x) if cutter['right'] >= x >= cutter['left']: result.append([x, cutter['bottom']]) cur_index += 1 continue cur_index += 1 if result: canvas.draw_line(cfg.int_n(result[0][0]), cfg.int_n(result[0][1]), cfg.int_n(result[1][0]), cfg.int_n(result[1][1]), color, 'result') return time.time() - start
def cyrus_beck_cut(canvas, cutter, sections): if canvas.start and canvas.old and canvas.start != canvas.old: mb.showerror( 'Ошибка', 'Перед использованием алгоритма необходимо замкнуть область') return None if not is_convex(cutter): mb.showerror('Ошибка', 'Многоугольник должен быть выпуклым') return None color = canvas.frame.colors['result'] verteces = [] for edge in cutter: verteces.extend([edge[0].x, edge[0].y]) canvas.create_polygon(*verteces, outline=canvas.frame.colors['cutter'], fill='white', tag='result') normals = get_normals(cutter) for section in sections: flag_break = False t_start, t_end = 0, 1 d = get_vector(section) length = len(cutter) for i in range(length): if cutter[i][0] != section[0]: wi = get_vector([cutter[i][0], section[0]]) else: wi = get_vector([cutter[(i + 1) % length][0], section[0]]) dck = scalar_multiplication(d, normals[i]) wck = scalar_multiplication(wi, normals[i]) if dck == 0: if scalar_multiplication(wi, normals[i]) < 0: flag_break = True break else: continue t = -wck / dck if dck > 0: if t > t_start: t_start = t else: if t < t_end: t_end = t if t_start > t_end: break if flag_break: continue if t_start < t_end: canvas.draw_line(cfg.int_n(section[0].x + d.x * t_start), cfg.int_n(section[0].y + d.y * t_start), cfg.int_n(section[0].x + d.x * t_end), cfg.int_n(section[0].y + d.y * t_end), color, 'result')