from oriented_matroid import * from meta_function import * from smc import * from combtools import * import cv2 import numpy as np from combtools import colors_list,colorbgr_list """ given a rank-2 acyclic uniform oriented matroid M, we try to draw a realization on it in 2D a double right click add a point we can move a point by letting the right click pressed at a small distance of a given point """ ######################## Functions ##################################################################################### # TODO: ATTENTION IL FAUT RETIRER LE FAIT LE POUVOIR CLIC GAUCHE QUAND ON A LE CLIC DROIT ENFONCé ! def draw_chirotope(chirot: Chirotope, points:tuple=None): # Etant donné un chirotope réalisable en 2D, permet à l'utilisateur d'essayé de le réaliser. chirot = chirot.opp() # first we take the reflexion since in opencv the axe y is reversed. if not points: points = chirot.get_ground_set() n = len(points) size = 512 assert chirot.get_rank() == 3 dict_point = {} # Variables to add points. i = 0 p = points[i] # Variables to move point oldx = None oldy = None moving_point = None oldimg = None #clic event, draw a point if the specified x,y is black def draw_point(event,x,y,flags,param): nonlocal dict_point,p,i,n,points,img,oldx,oldy,moving_point,oldimg def reset_img(): nonlocal img img = np.zeros(img.shape) def write_point(): nonlocal dict_point,img for point in dict_point: cv2.circle(img, dict_point[point], 3, (0, 0, 255), cv2.FILLED) cv2.putText(img, str(point), dict_point[point], fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(0, 0, 255), thickness=1) def draw_cell_for_next_points(): nonlocal img,dict_point,i,points set_image = {(y, x) for y in range(0, img.shape[0]) for x in range(0, img.shape[1])} if i >= 1 and i < n - 1: for j in range(0, len(dict_point) - 1): pj = points[j] for k in range(j + 1, len(dict_point)): pk = points[k] tup = (pj, pk, points[i+1]) color_side_det(img, dict_point[pj], dict_point[pk], sign_perm(tup)*chirot[tuple(sorted(tup))], set_image) def draw_cell_for_moving_point(): nonlocal img,dict_point set_image = {(y, x) for y in range(0, img.shape[0]) for x in range(0, img.shape[1])} for j in range(0, len(dict_point)): if points[j] != moving_point: for k in range(j + 1, len(dict_point)): if points[k] != moving_point: pj = points[j] pk = points[k] triplet = (pj, pk, moving_point) color_side_det(img, dict_point[pj], dict_point[pk], sign_perm(triplet) * chirot[tuple(sorted(triplet))], set_image) # Add a point when left clicking if event == cv2.EVENT_LBUTTONDBLCLK: if i < n: if tuple(img[y,x]) != (255.,255.,255.): p = points[i] dict_point[p] = (x,y) reset_img() draw_cell_for_next_points() write_point() i += 1 cv2.imshow("Draw", img) # Target a point when pressing right click if event == cv2.EVENT_RBUTTONDOWN: # We need to be able to detect if we clicked on a point. # For calculate the manhattan distance between x,y and all the point in dict_point. # We keep the closest one if one is at a small enough distance. def hamming_distance(p1,p2): return abs(p2[0]-p1[0])+abs(p2[1]-p1[1]) moving_point = min(dict_point,key=lambda a: hamming_distance((x,y),dict_point[a])) if hamming_distance(dict_point[moving_point],(x,y)) > 3: moving_point = None print(moving_point) if moving_point or moving_point==0: # Reset the picture reset_img() # Add the white pixels draw_cell_for_moving_point() # Draw the points write_point() cv2.imshow("Draw",img) # If right click is released on a correct coordinate, then move the point, otherwise do nothing. if event == cv2.EVENT_RBUTTONUP: if moving_point or moving_point==0: if tuple(img[y,x]) != (255,255,255): dict_point[moving_point] = (x,y) moving_point = None else: moving_point = None reset_img() draw_cell_for_next_points() write_point() cv2.imshow("Draw", img) img = np.zeros((size,size,3)) cv2.imshow("Draw",img) cv2.setMouseCallback('Draw', draw_point) while 1: if cv2.waitKey(0)!= ord("q"): break geom = GeometricModel(points,3,dict_point) print(chiro(geom)) # Attention au scaling de l'image def deform_geom(geom: GeometricModel): chirot = chiro(geom) chirot = chirot.opp() # first we take the reflexion since in opencv the axe y is reversed. n = geom.get_n() size = 512 assert chirot.get_rank() == 3 dict_point = geom._dict_points dict_point = {p:(int(dict_point[p][0]*400+200),int(dict_point[p][1]*400+200)) for p in dict_point} print(dict_point) oldx = None oldy = None moving_point = None oldimg = None points = geom.get_ground_set() # clic event, draw a point if the specified x,y is black def draw_point(event, x, y, flags, param): nonlocal dict_point,n, img, oldx, oldy, moving_point, oldimg def reset_img(): nonlocal img img = np.zeros(img.shape) def write_point(): nonlocal dict_point, img for point in dict_point: cv2.circle(img, dict_point[point], 3, (0, 0, 255), cv2.FILLED) cv2.putText(img, str(point), dict_point[point], fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(0, 0, 255), thickness=1) def draw_cell_for_moving_point(): nonlocal img, dict_point set_image = {(y, x) for y in range(0, img.shape[0]) for x in range(0, img.shape[1])} for j in range(0, len(dict_point)): if points[j] != moving_point: for k in range(j + 1, len(dict_point)): if points[k] != moving_point: pj = points[j] pk = points[k] triplet = (pj, pk, moving_point) color_side_det(img, dict_point[pj], dict_point[pk], sign_perm(triplet) * chirot[tuple(sorted(triplet))], set_image) # Target a point when pressing right click if event == cv2.EVENT_LBUTTONDOWN: # We need to be able to detect if we clicked on a point. # For calculate the manhattan distance between x,y and all the point in dict_point. # We keep the closest one if one is at a small enough distance. def hamming_distance(p1, p2): return abs(p2[0] - p1[0]) + abs(p2[1] - p1[1]) moving_point = min(dict_point, key=lambda a: hamming_distance((x, y), dict_point[a])) if hamming_distance(dict_point[moving_point], (x, y)) > 3: moving_point = None print(moving_point) if moving_point or moving_point == 0: # Reset the picture reset_img() # Add the white pixels draw_cell_for_moving_point() # Draw the points write_point() cv2.imshow("Draw", img) # If right click is released on a correct coordinate, then move the point, otherwise do nothing. if event == cv2.EVENT_LBUTTONUP: if moving_point or moving_point == 0: if tuple(img[y, x]) != (255, 255, 255): dict_point[moving_point] = (x, y) moving_point = None else: moving_point = None reset_img() write_point() cv2.imshow("Draw", img) img = np.zeros((size, size, 3)) for point in dict_point: cv2.circle(img, dict_point[point], 3, (0, 0, 255), cv2.FILLED) cv2.putText(img, str(point), dict_point[point], fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(0, 0, 255), thickness=1) cv2.imshow("Draw", img) cv2.setMouseCallback('Draw', draw_point) while 1: if cv2.waitKey(0) != ord("q"): break ########################### coding blocks ############################################################################## def get_line_points(p1, p2, img_shape): """ Merci chatgpt ! :param p1: :param p2: :param img_shape: :return: """ height, width = img_shape[:2] # Calculer les coefficients de la droite y = ax + b if p1[0] != p2[0]: # Éviter la division par zéro a = (p2[1] - p1[1]) / (p2[0] - p1[0]) b = p1[1] - a * p1[0] else: a = float('inf') # Droite verticale b = p1[0] # x = b # Trouver les points d'intersection avec les bords de l'image points = [] if a != float('inf'): # Intersection avec le bord gauche (x = 0) y0 = b if 0 <= y0 < height: points.append((0, int(y0))) # Intersection avec le bord droit (x = width) y_width = a * width + b if 0 <= y_width < height: points.append((width, int(y_width))) # Intersection avec le bord supérieur (y = 0) if a != 0 and a != float('inf'): x0 = -b / a if 0 <= x0 < width: points.append((int(x0), 0)) # Intersection avec le bord inférieur (y = height) x_height = (height - b) / a if 0 <= x_height < width: points.append((int(x_height), height)) # Pour une droite verticale if a == float('inf'): if 0 <= b < width: points.append((int(b), 0)) points.append((int(b), height)) return points def color_side_det(image, p1, p2,sign,set_image): """ Merci chatgpt ! :param image: :param p1: :param p2: :return: """ height, width = image.shape[:2] if p1[0] != p2[0]: a = (p2[1] - p1[1]) / (p2[0] - p1[0]) b = p1[1] - a * p1[0] else: a = float('inf') b = p1[0] for coord in list(set_image): y = coord[0] x = coord[1] deter = p1[0] * p2[1] - p1[1] * p2[0] - (p1[0] * y - p1[1] * x) + (p2[0] * y - p2[1] * x) if deter * sign >= 0: image[y, x] = [255, 255, 255] set_image.remove(coord)