def handleRotation(): #rotaciona o polígono selecionado de acordo com a angulação #entre o cursor neste frame e o cursor no frame passado #em relação à articulação selecionada global lastMousePoint polygon = polygons[selected_polygon] p1 = lastMousePoint p2 = currentMousePoint p3 = joints[selected_joint].global_pos u = Point(p3.x - p1.x, p3.y - p1.y) v = Point(p3.x - p2.x, p3.y - p2.y) length_u = sqrt(u.x * u.x + u.y * u.y) length_v = sqrt(v.x * v.x + v.y * v.y) dot = u.x * v.x + u.y * v.y cos = dot / float(length_u * length_v) cos = min(cos, 1) #corrige erros de aproximação que tornam o cosseno > 1 angle = acos(cos) sign = (p2.x - p1.x) * (p3.y - p2.y) - (p2.y - p1.y) * ( p3.x - p2.x) #detecta orientação da rotação sign = 1 if sign > 0 else -1 angle = angle * sign p, j = getChildren(polygon) for poly in p: poly.rotate(p3, angle) for joint in j: joint.rotate(p3, angle) lastMousePoint = currentMousePoint
def getIntersection(line_1, line_2): p = line_1.src r = Point(line_1.dst.x - line_1.src.x, line_1.dst.y - line_1.src.y) q = line_2.src s = Point(line_2.dst.x - line_2.src.x, line_2.dst.y - line_2.src.y) if (r.x == 0 and r.y == 0) or (s.x == 0 and s.y == 0): return None #ponto qp = Point(q.x - p.x, q.y - p.y) pq = Point(p.x - q.x, p.y - q.y) r_x_s = crossProduct(r, s) qp_x_r = crossProduct(qp, r) if r_x_s == 0 and qp_x_r == 0: return None #colinear qp_x_s = crossProduct(qp, s) pq_x_r = crossProduct(pq, r) s_x_r = crossProduct(s, r) if r_x_s == 0 and qp_x_r != 0: return None #paralelo t = float(qp_x_s) / float(r_x_s) u = float(pq_x_r) / float(s_x_r) if r_x_s != 0 and (t > 0 and t < 1) and (u > 0 and u < 1): return Point(p.x + t * r.x, p.y + t * r.y) #interseção! else: return None #sem interseção
def onMouse1Down(x, y): global currentState global lastMousePoint global selected_polygon global selected_joint if currentState == ApplicationState.NONE: #caso a aplicação não esteja fazendo nada, checamos se um polígono foi clicado polygonClicked = getFirstPolygonClicked() lastMousePoint = Point(x, y) if polygonClicked is not None: selected_joint = getPolygonParentJoint(polygonClicked) selected_polygon = polygonClicked.p_id #se polígono clicado não é dependente de nenhuma articulação, #inicia-se a translação dele e dos polígonos conectados a ele if selected_joint == -1: currentState = ApplicationState.MOVING_POLYGON polygonClicked.update_offset(currentMousePoint) p, j = getConnectedPolygons(polygonClicked) for poly in p: poly.update_offset(currentMousePoint) for joint in j: joint.update_offset(currentMousePoint) #se ele depende de alguma articulação, iniciamos a rotação else: currentState = ApplicationState.ROTATING_POLYGON else: #se nenhum polígono foi clicado, começamos a desenhar currentState = ApplicationState.DRAWING_POLYGON
def worldToScreenPoint(coord): width = glutGet(GLUT_WINDOW_WIDTH) height = glutGet(GLUT_WINDOW_HEIGHT) return Point((float((width / float(2))) - coord.x) / float(((-width) / 2)), (float((height / float(2))) - coord.y) / float( (height / float(2))))
def pointInsidePolygon(point, polygon): line = Line(point, Point(0, 0)) intersections = 0 polygon_lines = [] for i in range(0, len(polygon.global_pts) - 1): aux = Line(polygon.global_pts[i], polygon.global_pts[i + 1]) polygon_lines.append(aux) aux = Line(polygon.get_last_point(), polygon.get_first_point()) polygon_lines.append(aux) for l in polygon_lines: if getIntersection(line, l): intersections += 1 return intersections % 2 == 1
def onMouse1Up(x, y): global drawingPolygon global lastMousePoint global previewLines global currentState global selected_joint global selected_polygon if currentState == ApplicationState.DRAWING_POLYGON: #se um polígono foi fechado, checamos se ele é válido e o criamos. if len(previewLines) > 0 and currentMousePoint.distance( previewLines[0].src) < 10: currentState = ApplicationState.NONE aux = list(previewLines) aux.append(Line(lastMousePoint, previewLines[0].src)) if hasIntersection(aux): previewLines = [] return polygons.append(Polygon(aux, len(polygons))) previewLines = [] return #caso contrário, checamos se esta linha é válida #e se for, começamos a pré-visualizá-la lines = list(previewLines) lines.append(Line(lastMousePoint, currentMousePoint)) if not hasIntersection(lines): previewLines.append(Line(lastMousePoint, currentMousePoint)) lastMousePoint = Point(currentMousePoint.x, currentMousePoint.y) #se estávamos movendo ou rotacionando um polígono, agora não estamos mais elif currentState == ApplicationState.MOVING_POLYGON: currentState = ApplicationState.NONE selected_polygon = -1 elif currentState == ApplicationState.ROTATING_POLYGON: currentState = ApplicationState.NONE selected_polygon = -1 selected_joint = -1
def mousePosUpdater(x, y): global currentMousePoint currentMousePoint = Point(x, y)
ROTATING_POLYGON = 3 currentState = ApplicationState.NONE #armazenam os objetos da cena atual previewLines = [] polygons = [] joints = [] #armazenam os IDs dos objetos selecionados (quando necessário) selected_joint = -1 selected_polygon = -1 #armazenam informações sobre a posição do mouse lastMousePoint = Point(0, 0) currentMousePoint = Point(0, 0) #desenha a cena como um todo def displayCallback(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() #desenha os polígonos e as articulações que os conectam for polygon in polygons: drawPolygon(polygon) for joint in joints: if joint.connected(polygon): drawPoint(joint.global_pos)