def main(): q = Quadrant((50, 50), (100, 100)) c = q.empty_quadrant(2) print(c.max_coordinates, c.min_coordinates) # q.add_point(Point([20, 60])) # print(q.min_coordinates, q.max_coordinates) # q.update(Quadrant((60,60),(180,180))) # print(q.min_coordinates, q.max_coordinates) # l = q.limits(0) # print(l) # print(q.get_arrays()) q.inflate(10) print(q.max_coordinates, q.min_coordinates)
def create_tree_dense(root, distance, globalroot): """à partir du quadrant dense root on crée un r-tree (remplit) de taille appropriée par ex en 2D cette fonction rajoute à l'arbre 4 quadrants découpant le root en quatre: de coordinates (xmin,ymin,xmoy,ymoy),(xmin,ymoy,xmoy,ymax), (xmoy, ymin, xmax,ymoy), (xmoy, ymoy, xmax,ymax) le reste se fait par la magie de la récursivité""" root.dense = True if condition_continue_dense(root, distance): Lchilds = [] lmax = [x for x in root.max_coordinates] lmin = [x for x in root.min_coordinates] lmoy = [(x + y) / 2 for x, y in zip(lmax, lmin)] L_liste_coordinates_child_min = [] L_liste_coordinates_child_max = [] for mi, mo, ma in zip(lmin, lmoy, lmax): L_liste_coordinates_child_min.append([mi, mo]) L_liste_coordinates_child_max.append([mo, ma]) bon_iterable = zip(product(*L_liste_coordinates_child_min), product(*L_liste_coordinates_child_max)) for coomins, coomaxs in bon_iterable: Lchilds.append(Quadrant(coomins, coomaxs)) for child in Lchilds: for p in root.list_point_inside: if child.contain(p): child.list_point_inside.append(p) # child.minimal_bounding() #can be interesting in some cases, # though it has a 'high' O(nbr_points_in_quadrant) complexity root.childs.append(child) child.parent = root create_tree_dense(child, distance, globalroot) else: globalroot.leafs.append(root)
def trouve_inclusions_diviser(polygones): results = [-1] * len(polygones) rectangle = Quadrant.empty_quadrant(2) for polygone in polygones: rectangle.update(polygone.bounding_quadrant()) trouve_inclusions_rec(polygones, results, rectangle) return results
def bounding_quadrant(self): """ return min quadrant containing self. """ quadrant = Quadrant.empty_quadrant(2) for point in self.endpoints: quadrant.add_point(point) return quadrant
def bounding_quadrant(self): """ return min quadrant containing underlying objects. """ quadrant = Quadrant.empty_quadrant(2) for point in self.vertices: quadrant.add_point(point) return quadrant
def bounding_quadrant(self): """ min quadrant containing polygon. """ box = Quadrant.empty_quadrant(2) for point in self.points: box.add_point(point) return box
def compute_displays(things): """ compute bounding quadrant and svg strings for all things to display. """ quadrant = Quadrant.empty_quadrant(2) strings = [] for color, thing in zip(cycle(iter(Displayer.svg_colors)), things): strings.append('<g fill="{}" stroke="{}">\n'.format(color, color)) inner_quadrant, inner_strings = compute_display(thing) quadrant.update(inner_quadrant) strings.extend(inner_strings) strings.append('</g>\n') return (quadrant, strings)
def create_tree(root, distance, globalroot): """à partir du quadrant root on crée un r-tree (remplit) de taille appropriée par ex en 2D cette fonction rajoute à l'arbre 4 quadrants découpant le root en quatre: de coordinates (xmin,ymin,xmoy,ymoy),(xmin,ymoy,xmoy,ymax), (xmoy, ymin, xmax,ymoy),(xmoy, ymoy, xmax,ymax) sans oublier d'avoir d'agrandir de distance les quadrants pour avoir tous les points (c'est un peu plus compliqué mais c'est l'idée""" continuer = condition_continue(root, distance) if continuer > 0: Lchilds = [] # tout cela sert à découper le quadrant parent en quadrants enfants lmax = [x for x in root.max_coordinates] lmin = [x for x in root.min_coordinates] lmoy = [(x + y) / 2 for x, y in zip(lmax, lmin)] L_liste_coordinates_child_min = [] L_liste_coordinates_child_max = [] for mi, mo, ma in zip(lmin, lmoy, lmax): L_liste_coordinates_child_min.append([mi, mo]) L_liste_coordinates_child_max.append([mo, ma]) bon_iterable = zip(product(*L_liste_coordinates_child_min), product(*L_liste_coordinates_child_max)) for coomins, coomaxs in bon_iterable: Lchilds.append(Quadrant(coomins, coomaxs)) # on ajoute les points_inside et le quadrant agrandi aux enfants, qu'on ajoute finalement au parent for child in Lchilds: child.extended = child.copy() child.extended.inflate(distance) for p in root.extended.list_point_inside: if child.extended.contain(p): child.extended.list_point_inside.append(p) if child.contain(p): child.list_point_inside.append(p) # child.minimal_bounding() #can be interesting in some cases, # though it has a 'high' O(nbr_points_in_quadrant) complexity root.childs.append(child) child.parent = root create_tree(child, distance, globalroot) # on décide si on continue ou pas la recursion, voire passer en mode dense elif continuer == 0: globalroot.leafs.append(root) else: # continuer <0 create_tree_dense(root, distance, globalroot)
def compute_display(thing): """ return bounding quadrant and svg strings for one thing (and all it's content) """ quadrant = Quadrant.empty_quadrant(2) strings = [] try: iterator = iter(thing) for subthing in iterator: inner_quadrant, inner_strings = compute_display(subthing) strings.extend(inner_strings) quadrant.update(inner_quadrant) except TypeError: # we cannot iterate on it strings.append(thing.svg_content()) quadrant.update(thing.bounding_quadrant()) return quadrant, strings
def bounding_quadrant(self): """ return min quadrant containing point. this method is defined on any displayable object. """ return Quadrant(self.coordinates, self.coordinates)
def print_components_sizes_not_random(distance, points, dimension, min_coo, max_coo): """ affichage des tailles triees de chaque composante methode par r-tree de taille distance il est conseillé de fold (replier) les fonctions create_tree* pour une meilleure compréhension du programme """ from geo.quadrant import Quadrant from itertools import product def condition_continue(quadrant, distance): """condition selon laquelle on continue la recursion pour créer l'arbre, on s'arrete ou on passe aux quadrants denses""" if (len(quadrant.extended.list_point_inside) > 256) and (quadrant.taille('max') <= 3 * distance): return -1 return (len(quadrant.list_point_inside) > 8) and (quadrant.taille('max') > 2 * distance) def condition_continue_dense(quadrant, distance): """permet de stopper la recursion pour les quadrants denses""" dimension = len(quadrant.min_coordinates) return (len(quadrant.list_point_inside) > 0) and (quadrant.taille('max') > distance / sqrt(dimension)) def create_tree_dense(root, distance, globalroot): """à partir du quadrant dense root on crée un r-tree (remplit) de taille appropriée par ex en 2D cette fonction rajoute à l'arbre 4 quadrants découpant le root en quatre: de coordinates (xmin,ymin,xmoy,ymoy),(xmin,ymoy,xmoy,ymax), (xmoy, ymin, xmax,ymoy), (xmoy, ymoy, xmax,ymax) le reste se fait par la magie de la récursivité""" root.dense = True if condition_continue_dense(root, distance): Lchilds = [] lmax = [x for x in root.max_coordinates] lmin = [x for x in root.min_coordinates] lmoy = [(x + y) / 2 for x, y in zip(lmax, lmin)] L_liste_coordinates_child_min = [] L_liste_coordinates_child_max = [] for mi, mo, ma in zip(lmin, lmoy, lmax): L_liste_coordinates_child_min.append([mi, mo]) L_liste_coordinates_child_max.append([mo, ma]) bon_iterable = zip(product(*L_liste_coordinates_child_min), product(*L_liste_coordinates_child_max)) for coomins, coomaxs in bon_iterable: Lchilds.append(Quadrant(coomins, coomaxs)) for child in Lchilds: for p in root.list_point_inside: if child.contain(p): child.list_point_inside.append(p) # child.minimal_bounding() #can be interesting in some cases, # though it has a 'high' O(nbr_points_in_quadrant) complexity root.childs.append(child) child.parent = root create_tree_dense(child, distance, globalroot) else: globalroot.leafs.append(root) def create_tree(root, distance, globalroot): """à partir du quadrant root on crée un r-tree (remplit) de taille appropriée par ex en 2D cette fonction rajoute à l'arbre 4 quadrants découpant le root en quatre: de coordinates (xmin,ymin,xmoy,ymoy),(xmin,ymoy,xmoy,ymax), (xmoy, ymin, xmax,ymoy),(xmoy, ymoy, xmax,ymax) sans oublier d'avoir d'agrandir de distance les quadrants pour avoir tous les points (c'est un peu plus compliqué mais c'est l'idée""" continuer = condition_continue(root, distance) if continuer > 0: Lchilds = [] # tout cela sert à découper le quadrant parent en quadrants enfants lmax = [x for x in root.max_coordinates] lmin = [x for x in root.min_coordinates] lmoy = [(x + y) / 2 for x, y in zip(lmax, lmin)] L_liste_coordinates_child_min = [] L_liste_coordinates_child_max = [] for mi, mo, ma in zip(lmin, lmoy, lmax): L_liste_coordinates_child_min.append([mi, mo]) L_liste_coordinates_child_max.append([mo, ma]) bon_iterable = zip(product(*L_liste_coordinates_child_min), product(*L_liste_coordinates_child_max)) for coomins, coomaxs in bon_iterable: Lchilds.append(Quadrant(coomins, coomaxs)) # on ajoute les points_inside et le quadrant agrandi aux enfants, qu'on ajoute finalement au parent for child in Lchilds: child.extended = child.copy() child.extended.inflate(distance) for p in root.extended.list_point_inside: if child.extended.contain(p): child.extended.list_point_inside.append(p) if child.contain(p): child.list_point_inside.append(p) # child.minimal_bounding() #can be interesting in some cases, # though it has a 'high' O(nbr_points_in_quadrant) complexity root.childs.append(child) child.parent = root create_tree(child, distance, globalroot) # on décide si on continue ou pas la recursion, voire passer en mode dense elif continuer == 0: globalroot.leafs.append(root) else: # continuer <0 create_tree_dense(root, distance, globalroot) #"""modifie la liste de points en les regroupants en (cluster de) composantes connexes""" # debut du programme :-) distance2 = distance**2 Root = Quadrant(min_coo, max_coo) Root.extended = Root Root.list_point_inside = points create_tree(Root, distance, Root) # on crée un r-tree (spécial) # les quadrants denses sont de cotés <=1/sqrt(dimension) donc tous les points intérieurs sont liés dense_leafs = [quadrant for quadrant in Root.leafs if quadrant.dense] normal_leafs = [quadrant for quadrant in Root.leafs if not quadrant.dense] # on va fusionner tous les points dans les mêmes quadrants denses dans les mêmes clusters for quadrant in dense_leafs: # on fusionne tous les clusters dans les quadrants denses if quadrant.list_point_inside: # if not empty p1 = quadrant.list_point_inside[0] p1.cluster.merge_with_all( [point.cluster for point in quadrant.list_point_inside]) # on va fusionner les clusters des points dans des quadrants denses différents for quadrant in dense_leafs: for another_quadrant in dense_leafs: if quadrant.lies(another_quadrant, distance): quadrant.list_point_inside[0].cluster.merge_with( another_quadrant.list_point_inside[0].cluster) for quadrant in normal_leafs: # on fusionne tous les clusters dans les quadrants normaux for p1 in quadrant.list_point_inside: for p2 in quadrant.extended.list_point_inside: if p1.distance_carre_to(p2) <= distance2: p1.cluster.merge_with(p2.cluster) longueurs = [] # On utilise defaultdict car ainsi vérifier qu'un cluster a été ID_prises = defaultdict(bool) # parcouru est en O(1) for point in points: if not ID_prises[point.cluster.ID]: ID_prises[point.cluster.ID] = True longueurs.append(point.cluster.count) print(sorted(longueurs, reverse=True))