class Viewport(Window): def __init__(self, x_min, y_min, x_max, y_max): super().__init__(x_min, y_min, x_max, y_max) self.t = Transform() def setWindow(self, window): self.window = window def transform(self, x, y): xw_min, yw_min = self.window.getMin()["x"], self.window.getMin()["y"] xw_max, yw_max = self.window.getMax()["x"], self.window.getMax()["y"] xvp_min, yvp_min = self.x_min, self.y_min xvp_max, yvp_max = self.x_max, self.y_max denormalized_point = self.t.denormalize(x, y) xvp = ((denormalized_point["x"] - xw_min) / (xw_max - xw_min)) * (xvp_max - xvp_min) yvp = (1 - (denormalized_point["y"] - yw_min) / (yw_max - yw_min)) * (yvp_max - yvp_min) #print(xvp, yvp) return {"x": xvp, "y": yvp} def transformadaViewPortCoordenada(self, x, y): xw_min, yw_min = self.window.getMin()["x"], self.window.getMin()["y"] xw_max, yw_max = self.window.getMax()["x"], self.window.getMax()["y"] xvp_min, yvp_min = self.x_min, self.y_min xvp_max, yvp_max = self.x_max, self.y_max xvp = ((x - xw_min) / (xw_max - xw_min)) * (xvp_max - xvp_min) yvp = (1 - (y - yw_min) / (yw_max - yw_min)) * (yvp_max - yvp_min) return {"x": xvp, "y": yvp}
class Shape: def __init__(self, name): self.world_coords = [] self.normalized_coords = [] self.name = name self.id = generateRandomId() self.transform = Transform() def addCoords(self, x, y, z = 1): self.world_coords.append({"x": x, "y": y, "z": z}) self.normalized_coords.append(self.transform.normalize(x, y)) def popCoords(self): self.world_coords.pop() self.normalized_coords.pop() def getWorldCoords(self): return self.world_coords def getNormalizedCoords(self): return self.normalized_coords def scaleNormalizedCoords(self, percentage): center = self.transform.denormalize(0,0) # get world coordenates for current viewport center # get real world coordinates from normalized ones coords = self.transform.denormalizeList(self.normalized_coords) for i in range(len(coords)): temp = self.transform.scale( coords[i]["x"], coords[i]["y"], percentage, percentage, center["x"], center["y"] ) new_coords = self.transform.normalize(temp[0], temp[1]) self.normalized_coords[i] = {"x": new_coords["x"], "y": new_coords["y"]} def rotateNormalizedCoords(self, degrees): center = self.transform.denormalize(0,0) # get world coordenates for current viewport center # get real world coordinates from normalized ones coords = self.transform.denormalizeList(self.normalized_coords) for i in range(len(coords)): temp = self.transform.rotation(coords[i]["x"], coords[i]["y"], center["x"], center["y"], degrees) new_coords = self.transform.normalize(temp[0], temp[1]) self.normalized_coords[i] = {"x": new_coords["x"], "y": new_coords["y"]} def setWorldCoords(self, i, x, y): self.world_coords[i] = { "x": x, "y": y } self.normalized_coords[i] = self.transform.normalize(x, y) def normalizeCoords(self): for i in range(len(self.world_coords)): x, y = self.world_coords[i]["x"], self.world_coords[i]["y"] self.normalized_coords[i] = self.transform.normalize(x, y) def getName(self): return self.name def getId(self): return self.id def drawToViewport(self, ctx, viewport): # move context to initial point clipping = Clipping() point = viewport.transform(self.normalized_coords[0]["x"], self.normalized_coords[0]["y"]) ctx.move_to(point["x"],point["y"]) if(self.__class__.__name__ == "Point"): # print("{},{}".format(self.normalized_coords[0]["x"], self.normalized_coords[0]["y"])) if (self.normalized_coords[0]["x"] >= -1 and self.normalized_coords[0]["x"] <= 1 and self.normalized_coords[0]["y"] >= -1 and self.normalized_coords[0]["y"] <= 1): ctx.rel_line_to(1,1) # equivalent to ctx.line_to(x+1,y+1) ctx.stroke() else: if(self.__class__.__name__ == "Line"): clipped_coords = clipping.clipLine(self.normalized_coords) elif(self.__class__.__name__ == "Polygon"): clipped_coords = clipping.sutherland_hodgman_clipping(self.normalized_coords) else: coords = self.transform.calculatePointsBezier(self.normalized_coords) #coords = self.transform.calculateBSpline(self.normalized_coords) clipped_coords = [] temp_coords = [] for i in range(0,len(coords)-1): temp_coords = [] temp_coords.append(coords[i]) temp_coords.append(coords[i+1]) clipped = clipping.clipLine(temp_coords) if(clipped): clipped_coords.append(clipped[0]) clipped_coords.append(clipped[1]) if(clipped_coords): point = viewport.transform(clipped_coords[0]["x"], clipped_coords[0]["y"]) ctx.move_to(point["x"],point["y"]) for entry in clipped_coords: # 1st interation does move_to and line_to to same point x2, y2 = entry["x"], entry["y"] point2 = viewport.transform(x2, y2) ctx.line_to(point2["x"],point2["y"]) if(self.__class__.__name__ is not "Curve"): ctx.close_path() ctx.stroke()