def detection_inclusion(polygones, point, nb_poly): """ renvoie tous les polygones dans lequel le polynome actuel (celui du segment) est inclus """ index_poly = -1 inclus_dans = [ ] # contient les polynomes dans lequel le polynome actuel (celui du segment) est inclus t = [ -1 for _ in range(len(polygones)) ] # contient le nombre d'intersections de chaque polynome avec le segment en question for poly in polygones: index_poly += 1 for segment in poly.segments(): point1 = Point(list(segment.endpoints[0].coordinates)) point2 = Point(list(segment.endpoints[1].coordinates)) x1 = point1.coordinates[0] y1 = point1.coordinates[1] x2 = point2.coordinates[0] y2 = point2.coordinates[1] x = point.coordinates[0] y = point.coordinates[1] if (y1 > y) != (y2 > y) and (x < (x2 - x1) * (y - y1) / (y2 - y1) + x1): # s'il y a une intersection t[index_poly] += 1 for j in range(len(t)): if t[j] % 2 == 0 and j != nb_poly: #le point est dedans et on verifie que chaque poly n'est pas inclus dans lui même inclus_dans.append(j) if len(inclus_dans) == 0: # la liste est vide => c'est inclus dans rien inclus_dans.append(-1) return inclus_dans
def intersection_test(): """ test the intersection on basic cases with one or two neighbours """ print("\n---------Intersection neighbour test---------") seg1 = Segment([Point([0, 0]), Point([2, 2])]) seg2 = Segment([Point([1, 0]), Point([1, 2])]) events = Events([seg1, seg2]) print("events:", events) Segment.current_point = Point([2.0, 2.0]) living_segments = SortedList() living_segments.add(seg1) living_segments.add(seg2) while not events.isempty(): current_event = events.event_list.pop(0) #print("current event: ", current_event.key) if current_event.key in events.begin_points: for segment in events.begin_points[current_event.key]: print("segment :", segment) print([point for point in intersect_with(segment, living_segments)]) print("-----------------------------------------\n")
def test_hashs(): """ fonction permettant de tester le hachage des points dans les differents carres. elle affiche la syntaxe svg correspondant au plan quadrille et les differents points de couleurs differentes selon le carre. le cote du carre est une valeur fixee dans le programme. pre-conditions: - points est un vecteur d'elements de type Point """ distance = 40 nbr = 400 // distance points = point_aleatoire(200, [0, 400]) print("test h1") quadrillage_vertical = [ Segment([Point([i * distance, 0]), Point([i * distance, 400])]) for i in range(nbr + 1) ] quadrillage_horizontal = [ Segment([Point([0, j * distance]), Point([400, j * distance])]) for j in range(nbr + 1) ] quadrillage = quadrillage_horizontal + quadrillage_vertical tycat(points, quadrillage) tables = divide_into_squares(distance, points) tycat(list(tables[0][carre]) for carre in tables[0]) print("test h2") print("test h3") print("test h4")
def main(): p = Point([1, 4]) # d = p.copy() # print(p) # print(d) # print(p.distance_to(Point([3,4]))) print(p.__add__(Point([2, 4])))
def print_components_sizes(distance, points): """ affichage des tailles triees de chaque composante """ segments = [] research_base = [point for point in points] d = distance / sqrt(2) n = int(1 / d) segments_horizentaux = [ Segment([Point([i * d, 0]), Point([i * d, 1])]) for i in range(n + 1) ] segments_verticaux = [ Segment([Point([0, i * d]), Point([1, i * d])]) for i in range(n + 1) ] origine = Point([0.0, 0.0]) total = research_base.copy() s = 0 while len(research_base) > 0: current = research_base[0] research_base.pop(0) for point in research_base: if current.distance_to(point) < distance: s += 1 segments.append(Segment([current, point])) tycat(origine, total, segments + segments_horizentaux + segments_verticaux)
def get_first_precision(self): """ Returns the length of the longer possible segment, to start the paving """ quadrant = self.bounding_quadrant() point_min = Point(quadrant.min_coordinates) point_max = Point(quadrant.max_coordinates) segmax = Segment([point_min, point_max]) maxlength = segmax.length() return 2 * maxlength
def generateur_polygones2(nb_poly): """Génère nb_poly carrés les uns dans les autres stockés dans un tableau""" tab = [] for indice in range(nb_poly): point1 = Point([0 + indice, 0 + indice]) point2 = Point([2 * nb_poly + 100 - indice, 0 + indice]) point3 = Point( [2 * nb_poly + 100 - indice, 2 * nb_poly + 100 - indice]) point4 = Point([0 + indice, 2 * nb_poly + 100 - indice]) tab.append(Polygon([point1, point2, point3, point4])) return tab
def main(): a = Point([0.7, 0.79]) b = Point([0.84, 0.62]) c = Point([b.x, a.y]) # tycat(points) d = a.cross_product(b, c) ab = a.distance_to(b) ac = a.distance_to(c) print(d) print(ab * ac) print(d / (ab * ac))
def living_key(segment, current_point, adjuster): """ key """ point = Point([current_point.coordinates[0] + 10, current_point.coordinates[1]]) other_point = Point([current_point.coordinates[0] - 10, current_point.coordinates[1]]) swipe_line = Segment([point, other_point]) intersection = segment.line_intersection_with(swipe_line) intersection = adjuster.hash_point(intersection) if intersection.coordinates[0] < current_point.coordinates[0]: return(intersection.coordinates[0], angle(segment, adjuster)) else: return(intersection.coordinates[0], angle(segment, adjuster))
def main_1(n, temps_1, fonction): """ Genere n points aleatoires et trace leur enveloppe convexe Stocke les performances dans un tableau temps_1 """ points = [Point((randint(5, 995), randint(5, 995))) for _ in range(n)] polygon_points = enveloppe_inc(points) polygone = Polygon(polygon_points) quadrant = polygone.bounding_quadrant() point_test = Point((200, 200)) start_1 = time() print(int(fonction(point_test, polygone, quadrant))) end_1 = time() temps_1.append(10000*(end_1 - start_1))
def square(cls, start_x, start_y, side): """ create a square, horizontally aligned. used in test scripts as a quick way to get polygons. """ starting_point = Point([start_x, start_y]) points = [ Point([0.0, 0.0]), Point([side, 0.0]), Point([side, side]), Point([0.0, side]), ] points = [p + starting_point for p in points] square_polygon = cls(points) return square_polygon
def print_quadrant(root): """marche uniquement en 2D""" xmin, ymin = root.min_coordinates xmax, ymax = root.max_coordinates p1 = Point([xmin, ymin]) p2 = Point([xmin, ymax]) p3 = Point([xmax, ymax]) p4 = Point([xmax, ymin]) s1 = Segment([p1, p2]) s2 = Segment([p2, p3]) s3 = Segment([p3, p4]) s4 = Segment([p4, p1]) print_segment([s1, s2, s3, s4]) if root.childs: for child in root.childs: print_quadrant(child)
def load_segments(filename): """ loads given .bo file. returns a vector of segments. """ coordinates_struct = struct.Struct('4d') segments = [] with open(filename, "rb") as bo_file: packed_segment = bo_file.read(32) while packed_segment: coordinates = coordinates_struct.unpack(packed_segment) points = [Point(coordinates[0:2]), Point(coordinates[2:])] segments.append(Segment(points)) packed_segment = bo_file.read(32) return segments
def scale(points, distance, max_coordinates, min_coordinates): """met à l'échelle (=> dans le carré (ou cube, etc...) unité)""" pmin = Point(min_coordinates) echelle = 1 / (max(max_coordinates) - min(min_coordinates)) nvpoints = [] for p in points: nvpoints.append((p - pmin) * echelle) return nvpoints, distance * echelle
def read_instance(fname): with open(fname, 'rt') as f: points = (tuple(map(float, l.split())) for l in f) # create polygons from [(l, x, y)] return [ Polygon([Point(p[1:]) for p in poly_points]) for _, poly_points in groupby(points, key=lambda t: t[0]) ]
def __init__(self, a, b, c, d): if not (isinstance(a, Point) and isinstance(b, Point) and isinstance(c, Point) and isinstance(d, Point)): raise TypeError("a, b, c, d should be Points") self._a = self._b = self._c = self._d = Point(0, 0) self._OK = False self._set(a, b, c, d) self._check()
def random_input_generator(nb_points, cas_general=1): """ fonction permettant de generer un couple (distance, points) où distance est un flottant aleatoire entre 0 et 0.2 et points un vecteur de nb_points objets de type Point. """ distance = random() / 6 if cas_general else 1 points = [Point([random(), random()]) for _ in range(nb_points)] return distance, points
def sweep_intersection(segment, current_point): """ computes and returns the abscissa of the intersection beetween the sweeping line and the segment. """ # Creates a segment that corresponds to the sweeping line around segment sweep = Segment([ Point([0, current_point.coordinates[1]]), Point([1, current_point.coordinates[1]]) ]) key_point = segment.line_intersection_with(sweep) # The key_point is None if segment is horizontal if key_point is not None: key_point = Segment.adjuster.hash_point(key_point) return key_point.coordinates else: return current_point.coordinates
def main(): """ petit exemple sur l'utilisation de tycat """ print("lancez moi dans terminology") print("tycat permet d'afficher des points et des segments") print("chaque argument doit etre un iterable sur des points \ et/ou segments (ou juste un point/segment)") print("chaque argument est affiche d'une couleur differente") # un point origine = Point([0.0, 0.0]) # un vecteur de points cercle = [Point([cos(c * pi / 10), sin(c * pi / 10)]) for c in range(20)] # un iterateur sur des segments (crees a la volee) segments = (Segment([p1, p2]) for p1, p2 in zip(cercle, islice(cycle(cercle), 1, None))) tycat(origine, cercle, segments)
def get_segments(polygones): max_length = 9999.0 couples_indice_segment = [] couples_indice_ligne = [] quadrants = [polygon.bounding_quadrant() for polygon in polygones] areas = [polygon.absolute_area for polygon in polygones] for indice, polygone in sorted(enumerate(polygones), key=lambda couple: couple[1].absolute_area): point = polygone.points[0].coordinates couples_indice_ligne.append(( indice, Segment( [Point([point[0], point[1]]), Point([max_length, point[1]])]), )) for segment in polygone.segments(): couples_indice_segment.append((indice, segment)) return couples_indice_segment, couples_indice_ligne, quadrants, areas
def load_segments(filename): """ loads given .bo file. returns a vector of segments. """ coordinates_struct = struct.Struct('4d') segments = [] adjuster = CoordinatesHash() with open(filename, "rb") as bo_file: packed_segment = bo_file.read(32) while packed_segment: coordinates = coordinates_struct.unpack(packed_segment) raw_points = [Point(coordinates[0:2]), Point(coordinates[2:])] adjusted_points = [adjuster.hash_point(p) for p in raw_points] segments.append(Segment(adjusted_points)) packed_segment = bo_file.read(32) return adjuster, segments
def load_instance(filename): """ loads .pts file. returns distance limit and points. """ with open(filename, "r") as instance_file: lines = iter(instance_file) distance = float(next(lines)) points = [Point([float(f) for f in l.split(",")]) for l in lines] return distance, points
def old_main(): """main function""" nombre_de_points = 100 coordonnees_des_points = 10 limit = random.randrange(2, nombre_de_points) polygones = [Polygon([Point([1, 2]), Point([2, 4]), Point([-1, 2])])] for _ in range(3): points = [ Point([ random.randrange(coordonnees_des_points), random.randrange(coordonnees_des_points), ]) ] segments = [] for _ in range(limit): # on ajoute le polygone si aucun de ses segments ne s'intersecte avec un segment déjà existant point = Point([ random.randrange(coordonnees_des_points), random.randrange(coordonnees_des_points), ]) print(points, segments) failed = is_failed(polygones, segments, points, point) if not failed: segment = Segment([points[-1], point]) if point not in points: points.append(point) if segment not in segments: segments.append(segment) if len(points) > 2: polygon = Polygon(points) if polygon.area() != 0: polygones.append(polygon) with open("generated.poly", "w") as file: for indice, polygone in enumerate(polygones): for point in polygone.points: file.write( f"{indice} {point.coordinates[0]} {point.coordinates[1]}\n" )
def detection_inclusion(polygones, point, poly, nb_poly): """ renvoie le polygone avec la plus petite aire dans lequel le polynome actuel (celui du point) est inclus """ index_poly = -1 inclus_dans = [ ] # contient le plus petit polygone dans lequel le polynome actuel (celui du point_de_depart) est inclus for poly2 in polygones: index_poly += 1 nb_intersect = 0 if abs(poly2.area()) > abs( poly.area() ): # on teste seulement les polygones avec une aire supérieure à celle de poly for segment in poly2.segments( ): # on teste chaque segment de poly2 point1 = Point(list(segment.endpoints[0].coordinates)) point2 = Point(list(segment.endpoints[1].coordinates)) x1 = point1.coordinates[0] y1 = point1.coordinates[1] x2 = point2.coordinates[0] y2 = point2.coordinates[1] x = point.coordinates[0] y = point.coordinates[1] if (y1 > y) != (y2 > y) and (x < (x2 - x1) * (y - y1) / (y2 - y1) + x1): # s'il y a une intersection nb_intersect += 1 if nb_intersect % 2 == 1 and len( inclus_dans ) == 0: # si on est inclus dans rien pour le moment min_area = abs(poly2.area()) # l'aire minimale inclus_dans.append(index_poly) elif nb_intersect % 2 == 1 and abs( poly2.area() ) < min_area: # si on est deja inclus dans un poly mais qu'on est inclus dans un autre avec une plus petite aire min_area = abs(poly2.area()) inclus_dans[0] = index_poly if len(inclus_dans) == 0: # si on est inclus dans aucun polygone inclus_dans.append(-1) return inclus_dans[0]
def main(): point1 = Point([1, 1]) point2 = Point([1, 5]) s = Segment([point1, point2]) # print(s) # print(s.endpoints) # c = s.copy() # print(c) # print(c.endpoints) # q = s.bounding_quadrant() # print(q) # print(q.min_coordinates, q.max_coordinates) # print(s.svg_content()) # point = Point([1,2]) # print(s.endpoints[0]) # print(s.endpoints[1]) # print(s.endpoint_not(point1)) # print(s.endpoint_not(point2)) # print(s.contains(Point([2, 4.5]))) a = s.__repr__() print(a)
def intersection(self, other): if not self: raise ValueError() elif isinstance(other, Line): if not self.intersecting(other): raise ValueError() det = self._a * other._b - other._a * self._b return Point(-(self._c * other._b - other._c * self._b) / det, -(self._a * other._c - other._a * self._c) / det) elif hasattr(other, 'intersection'): return other.intersection(self) else: raise NotImplementedError
def test_point_in_polygon_upper_triangles(function): polygone, point = ( Polygon( [ Point([-1, 0]), Point([0, 1]), Point([1, 0]), Point([2, 1]), Point([3, 0]), Point([2, -2]), Point([0, -2]), ] ), Point([2, 0]), ) assert function(polygone, point) == True
def point_aleatoire(nombre, bornes): """ fonction retourner un vecteur de nombre objets aleatoires de type Point. les abscisses et ordonnees des points generes sont comprises entre bornes[0] et bornes[1]. pre-conditions: - nombre est un entier """ points = [ Point([randint(bornes[0], bornes[1]), randint(bornes[0], bornes[1])]) for _ in range(nombre) ] return points
def hash_point(self, point): """ add a point to the hash, returning new point with adjusted coordinates. """ if point in self.fast_hash: return point new_coordinates = [ self.__hash_coordinate(c, i) for i, c in enumerate(point.coordinates) ] new_point = Point(new_coordinates) self.fast_hash.add(new_point) return new_point
def partition_segment(self, area): """ prend juste la partie du edge delimitee par la partition """ y_i, y_j = area[0], area[1] ptA = self.endpoints[0] ptB = self.endpoints[1] # Garder l'orientation du segment vecteur = self.segment_to_vector() # definir le point bas et le point haut du segment if ptA.y < ptB.y: pt_min, pt_max = ptA, ptB else: pt_min, pt_max = ptB, ptA # On nomine les abscisses des deux points definis auparavant x_min, x_max = pt_min.x, pt_max.x # On nomine les ordonnees des deux points definis auparavant y_min, y_max = pt_min.y, pt_max.y # Les cas particuliers if (y_min <= y_i and y_max <= y_i) or (y_max >= y_j and y_min >= y_j) or self.is_horizontal(): return None else: y_min_nv = max(y_i, y_min) y_max_nv = min(y_j, y_max) if self.is_vertical(): pt_min_nv = Point((x_min, y_min_nv)) pt_max_nv = Point((x_min, y_max_nv)) else: pente, ordonnee = self.equation_segment() x_min_nv = (y_min_nv - ordonnee)/pente x_max_nv = (y_max_nv - ordonnee)/pente pt_min_nv = Point((x_min_nv, y_min_nv)) pt_max_nv = Point((x_max_nv, y_max_nv)) new_edge = Segment([pt_min_nv, pt_max_nv]) return new_edge.orient_segment(vecteur)