def Rectangle(self): p1, p2 = arrange_points(self.points[-2:]) p3 = Point(int(p1.x), int(p2.y)) p4 = Point(int(p2.x), int(p1.y)) print("Rectangle {} {} {} {}".format(p3, p2, p4, p1)) self.DDA(p3, p2) self.DDA(p4, p2) self.DDA(p3, p1) self.DDA(p4, p1) self.last_rectangle = [p3, p2, p4, p1] self.points = []
def DDA(self, p1, p2, color='#ff0000'): p1, p2 = arrange_points([p1, p2]) p1, p2 = Point(int(p1.x), int(p1.y)), Point(int(p2.x), int(p2.y)) dy = p2.y - p1.y dx = p2.x - p1.x step = abs(dx if dx >= abs(dy) else dy) dx, dy = dx / step, dy / step while step > 0: y = self.canvas.winfo_reqheight() - int(p1.y) self.img.put(color, (int(p1.x), int(y))) p1.y += dy p1.x += dx step -= 1
def paint(self, event): y = self.canvas.winfo_reqheight() - event.y p1 = Point(event.x, y) print(p1) self.i += 1 self.try_create_pixel(p1) x1, y1 = (event.x - 1), (event.y - 1) x2, y2 = (event.x + 1), (event.y + 1) self.canvas.create_oval(x1, y1, x2, y2, fill=python_green, outline=python_green, width=4) if self.mode == self.start_polygon: print("Polygon mode") return if self.mode in [self.Rectangle, self.LB]: if not len(self.points) % 2: self.mode() else: self.mode()
def paint(self, event): p1 = Point(event.x, event.y) self.try_create_pixel(p1, append=True) if self.mode == self.cohen: if not len(self.points) % 2: self.mode() else: self.mode()
def try_create_pixel(self, p: Point, append: bool = False, color: str = '#ff0000'): if 0 < p.x < canvas_width and 0 < p.y < canvas_height: y = self.canvas.winfo_reqheight() - p.y if self.mode in [ self.vertex_sorting, self.draw_poly ] else p.y self.img.put(color, (p.x, y)) if append: print(y) self.points.append(Point(p.x, y))
def drawing_with_pen(self, p1, p2, color='#ff0000'): p1, p2 = arrange_points([p1, p2]) p1, p2 = Point(int(p1.x), int(p1.y)), Point(int(p2.x), int(p2.y)) dx, dy = p2.x - p1.x, p2.y - p1.y step = abs(dx if abs(dx) >= abs(dy) else dy) dx, dy = dx / step, dy / step brush_size = 3 matrix = self.rect_matrix(brush_size) while step > 0: idx = int(len(matrix) / 2) for i in range(len(matrix)): for j in range(len(matrix[i])): if matrix[i][j] != 0: new_point = Point( int(p1.x - idx + i), int(p1.y - int(len(matrix[i]) / 2) + j)) if 0 < new_point.x < canvas_width and 0 < new_point.y < canvas_height: y = self.canvas.winfo_reqheight() - new_point.y self.img.put(color, (new_point.x, y)) p1.y += dy p1.x += dx step -= 1
def DDA(self, point1, point2, color='#ff0000'): # Pseudocode void lineDDA(int x1, int y1, int x2, int y2){float dy = y2 - y1;float dx = x2 - x1;float m = dy/dx;float y = y1;for (int x = x1; x <= x2; ++x){putPixel(x, round(y));y += m;}} p1, p2 = copy(point1), copy(point2) print(f"DDA from {p1} to {p2}") dy = p2.y - p1.y dx = p2.x - p1.x step = abs(dx if abs(dx) >= abs(dy) else dy) print(dx, dy, step) dx, dy = dx / step, dy / step while step > 0: self.try_create_pixel(Point(int(p1.x), int(p1.y)), color=color) p1.y += dy p1.x += dx step -= 1
def LB(self): Point1, Point2 = arrange_points(self.points[-2:]) print("LB from {} to {}".format(Point1, Point2)) x1, y1 = Point1.x, Point1.y x2, y2 = Point2.x, Point2.y r1, r2, r3, r4 = arrange_rectangle_points(self.last_rectangle) xmin, ymin = r1.x, r1.y xmax, ymax = r4.x, r4.y p1 = -(x2 - x1) p2 = -p1 p3 = -(y2 - y1) p4 = -p3 q1 = x1 - xmin q2 = xmax - x1 q3 = y1 - ymin q4 = ymax - y1 # DONT USE LIST posarr, negarr = [1], [0] if (p1 == 0 and q1 < 0) or (p3 == 0 and q3 < 0): print("Line is parallel to clipping window!") return if p1 != 0: r1 = q1 / p1 r2 = q2 / p2 if p1 < 0: negarr.append(r1) posarr.append(r2) else: negarr.append(r2) posarr.append(r1) if p3 != 0: r3 = q3 / p3 r4 = q4 / p4 if p3 < 0: negarr.append(r3) posarr.append(r4) else: negarr.append(r4) posarr.append(r3) print(negarr, posarr) rn1 = max(negarr) rn2 = min(posarr) if rn1 > rn2: print("Line is outside the clipping window!") return xn1 = x1 + (p2 * rn1) yn1 = y1 + (p4 * rn1) xn2 = x1 + (p2 * rn2) yn2 = y1 + (p4 * rn2) self.DDA(Point(int(xn1), int(yn1)), Point(int(xn2), int(yn2))) if x1 != xn1 and y1 != yn1: self.DDA(Point(int(x1), int(y1)), Point(int(xn1), int(yn1)), '#0000ff') if x2 != xn2 and y2 != yn2: self.DDA(Point(int(x2), int(y2)), Point(int(xn2), int(yn2)), '#0000ff') self.points = []
def vertex_sorting(self): if len(self.polygon) < 2: return for idx in range(len(self.polygon)): self.polygon[idx].idx = idx self.DDA(self.polygon[-1], self.polygon[0]) sorted_points = arrange_points_by_yx(self.polygon) AET = [] indices = [point.idx for point in sorted_points] k = 0 i = indices[k] ymin = self.polygon[indices[0]].y ymax = self.polygon[indices[-1]].y y = ymin while y < ymax: while self.polygon[i].y == y: if self.polygon[i - 1].y > self.polygon[i].y: AET.append(EdgeBucket(self.polygon[i - 1], self.polygon[i])) if self.polygon[(i + 1) % len(self.polygon)].y > self.polygon[i].y: AET.append( EdgeBucket(self.polygon[(i + 1) % len(self.polygon)], self.polygon[i])) k += 1 if k >= len(indices): break i = indices[k] AET = sorted(AET, key=lambda e: e.x) for edge1, edge2 in self.iterate(AET): for x_iter in range(math.ceil(edge1.x), math.floor(edge2.x)): self.try_create_pixel(Point(x_iter, y), color="#0000FF") y += 1 AET = [edge for edge in AET if edge.ymax != y] for edge in AET: edge.x += edge.m_inverse
def cohen(self): if not self.cohen_rectangle: self.img = tk.PhotoImage(width=canvas_width, height=canvas_height) self.canvas.create_image((canvas_width // 2, canvas_height // 2), image=self.img, state="normal") p1, p3 = self.points[-2:] p2, p4 = Point(p3.x, p1.y), Point(p1.x, p3.y) print(f"Drawing rectangle from p1={p1} to p2={p2}") self.DDA(p1, p2) self.DDA(p2, p3) self.DDA(p3, p4) self.DDA(p4, p1) self.cohen_rectangle = Rectangle(p1.y, p3.x, p3.y, p1.x) return p1, p2 = self.points[-2:] clip = self.cohen_rectangle # From slides accept, done = False, False outcode1, outcode2 = compute_outcode(p1, clip), compute_outcode(p2, clip) while not done: print(f'{outcode1:b}, {outcode2:b}') if (outcode1 | outcode2) == 0: accept = True done = True elif (outcode1 & outcode2) != 0: accept = False done = True else: outcodeOut = outcode1 if outcode1 != 0 else outcode2 p = Point(None, None) if (outcodeOut & Outcodes.TOP) != 0: p.x = p1.x + (p2.x - p1.x) * (clip.top - p1.y) / (p2.y - p1.y) p.y = clip.top elif (outcodeOut & Outcodes.BOTTOM) != 0: p.x = p1.x + (p2.x - p1.x) * (clip.bottom - p1.y) / (p2.y - p1.y) p.y = clip.bottom elif (outcodeOut & Outcodes.RIGHT) != 0: p.y = p1.y + (p2.y - p1.y) * (clip.right - p1.x) / (p2.x - p1.x) p.x = clip.right elif (outcodeOut & Outcodes.LEFT) != 0: p.y = p1.y + (p2.y - p1.y) * (clip.left - p1.x) / (p2.x - p1.x) p.x = clip.left if outcodeOut == outcode1: p1 = p outcode1 = compute_outcode(p1, clip) else: p2 = p outcode2 = compute_outcode(p2, clip) if accept: self.DDA(p1, p2)