AccueilAlgorithmes & IAQuadtree

🌲 Quadtree

Simulation interactive de quadtree : dispersez des points, observez la subdivision 2D récursive, exécutez des requêtes de plage et de plus proche voisin, et comparez la phase large de collision à O(n²).

Algorithmes & IA3DModéré60 FPS
quadtree ↗ Ouvrir en autonome

À propos de l'index spatial Quadtree

Un quadtree est une structure de données arborescente dans laquelle chaque nœud interne subdivise sa région 2D en exactement quatre quadrants égaux (NO, NE, SO, SE), récursivement jusqu'à ce que chaque région feuille contienne au plus un nombre seuil de points (généralement un). Inventé par Raphael Finkel et J.L. Bentley en 1974 et popularisé en géométrie computationnelle tout au long des années 1980, les quadtrees réduisent les requêtes spatiales d'un temps de recherche linéaire O(n) à O(log n + k), où k est le nombre de résultats renvoyés. Ils constituent la structure d'accélération standard pour la détection de phase large de collision dans les moteurs de jeux 2D, les systèmes d'information géographique (SIG) et la compression d'images (les images codées en quadtree remplacent les régions uniformes par un seul nœud de couleur).

Ce simulateur vous permet de disperser des points aléatoires ou de cliquer pour les placer individuellement, puis observe l'arbre se subdiviser en temps réel à mesure que le seuil de capacité des nœuds est dépassé. Vous pouvez faire glisser un rectangle de requête de plage pour voir exactement quels quadrants sont visités et lesquels sont élagués, compter les nœuds visités par rapport à une recherche linéaire naïve, et observer comment des distributions de points groupées ou uniformes affectent la profondeur de l'arbre et l'efficacité des requêtes.

Questions fréquentes

Quelle est la complexité temporelle d'une requête de plage sur un quadtree ?

Pour un ensemble de n points aléatoires uniformes dans un carré unité, une requête de plage renvoyant k points visite en moyenne O(√n + k) nœuds — bien mieux que la recherche linéaire O(n). Dans le pire des cas (distributions de points très dégénérées ou requête couvrant de nombreux nœuds partiellement chevauchants), la borne monte à O(n), mais cela est rare en pratique. Le terme O(√n) provient du nombre de cellules du quadtree qui coupent la frontière de la requête sans y être entièrement contenues.

Comment un quadtree accélère-t-il la détection de collision dans les jeux ?

Dans un moteur physique 2D, vérifier toutes les paires d'objets pour une collision est en O(n²) — infaisable pour des centaines d'objets. Une phase large en quadtree fonctionne en insérant la boîte englobante de chaque objet dans l'arbre, puis en ne recherchant pour chaque objet que les objets dans les cellules feuilles identiques ou adjacentes. Si les objets sont répartis dans l'espace, le nombre moyen de candidats par objet chute à O(log n) ou moins, réduisant le coût total de la phase large à O(n log n). Des moteurs tels que Box2D, Unity 2D et LibGDX utilisent tous des arbres spatiaux (quadtrees ou arbres AABB) à cette fin.

Quelle est la différence entre un point quadtree et un quadtree PR (point-région) ?

Un point quadtree se divise aux coordonnées du point inséré — les quatre enfants représentent des quadrants centrés sur ce point. Un quadtree PR (point-région) divise l'espace à son point médian géométrique, quel que soit l'emplacement des points, donnant une structure de grille hiérarchique fixe. Les quadtrees PR sont plus prévisibles en profondeur (toujours ⌈log₂(D/ε)⌉ pour une résolution ε dans un domaine D) et plus faciles à implémenter sans équilibrage. Ce simulateur utilise la variante PR car la subdivision à point médian fixe rend l'animation visuelle plus nette.

Jusqu'à quelle profondeur un quadtree peut-il croître ?

La profondeur maximale d'un quadtree PR est bornée par la résolution du système de coordonnées. Pour des coordonnées en virgule flottante 32 bits dans un carré unité, la distance minimale distinguable est d'environ 10⁻⁷, donc l'arbre peut atteindre au plus ~23 niveaux avant que deux points « distincts » n'occupent la même feuille. Pour des coordonnées entières dans une grille de 1024×1024, la profondeur maximale est de 10 (puisque 2¹⁰ = 1024). En pratique, des arbres très profonds ne se forment que lorsque de nombreux points se regroupent dans une petite zone ; la profondeur moyenne pour un ensemble de points uniforme est O(log n).

Un quadtree peut-il gérer l'insertion et la suppression dynamiques de points ?

Oui. L'insertion parcourt de la racine jusqu'à la feuille appropriée en temps O(profondeur), divisant la feuille si elle dépasse sa capacité. La suppression retire le point et, si le nombre total de points du parent tombe sous le seuil de fusion, réunit les quatre nœuds enfants dans la feuille parent. Les deux opérations sont en moyenne O(log n) pour des points uniformément distribués. Des insertions et suppressions fréquentes dans un ensemble de points groupés peuvent nécessiter une reconstruction périodique pour éviter un déséquilibre sévère.

Qu'est-ce qu'un octree et quel est son lien avec un quadtree ?

Un octree est la généralisation 3D : chaque nœud subdivise son cube en huit sous-cubes égaux (octants). Les octrees sont largement utilisés dans les moteurs de jeux 3D, l'accélération du lancer de rayons et le traitement de nuages de points LiDAR. Les mêmes principes algorithmiques s'appliquent — requêtes de plage, recherche de plus proche voisin et phase large de collision bénéficient tous de la hiérarchie spatiale. En pratique, les arbres BVH 3D (hiérarchie de volumes englobants) surpassent souvent les octrees pour les scènes dynamiques car ils s'adaptent à la distribution des points plutôt que d'utiliser des divisions à point médian fixe.

Comment un quadtree est-il utilisé dans la compression d'images ?

Le codage d'image en quadtree divise récursivement une image en quadrants. Si tous les pixels d'un quadrant se situent dans un seuil d'une seule valeur de couleur, le quadrant est stocké comme un seul nœud feuille avec cette couleur — aucun stockage par pixel n'est nécessaire. Sinon, le quadrant est subdivisé à nouveau. Cela produit un schéma de compression sans perte (à seuil=0) ou avec perte (seuil>0). La compression d'image fractale (utilisée dans certains anciens jeux sur CD-ROM) est une technique apparentée. Les codecs modernes (HEVC, AV1) utilisent des hiérarchies d'unités de codage (CU) de type quadtree pour partitionner les images en blocs de taille variable pour le codage entropique.

Quel est l'algorithme de requête de plus proche voisin sur un quadtree ?

La recherche du plus proche voisin commence à la racine et descend dans le quadrant enfant contenant le point de requête, en maintenant un candidat « meilleur actuel ». En remontant la récursion, chaque quadrant frère est vérifié : si la distance minimale possible entre la requête et le quadrant (la distance de son coin le plus proche) est inférieure au meilleur actuel, le quadrant doit être exploré — sinon il est élagué. En pratique, cela visite O(log n) nœuds pour des données aléatoires uniformes, bien que le pire des cas (placement de points adversarial) soit O(n).

Quel est le rapport entre un quadtree et un arbre k-d ?

Un arbre k-d (arbre k-dimensionnel, Bentley 1975) est un arbre de partitionnement d'espace binaire qui alterne entre les axes de coordonnées pour ses divisions, en choisissant le point médian le long de l'axe courant comme valeur de division. Pour des données 2D, un arbre k-d alterne entre divisions en x et en y. Contrairement à un quadtree PR, un arbre k-d s'équilibre toujours parfaitement (profondeur O(log n) pour n points), mais il a de moins bonnes performances de cache et est plus difficile à mettre à jour dynamiquement. Empiriquement, les arbres k-d surpassent les quadtrees pour les ensembles de points statiques et les dimensions inférieures ; les quadtrees sont préférés pour les données 2D dynamiques et la phase large de collision.

Qu'est-ce que la « courbe en Z » et quel est son lien avec les quadtrees ?

La courbe en Z (Morton) associe des coordonnées 2D à un index 1D en entrelaçant les bits des coordonnées x et y : pour x = b₁b₂b₃ et y = c₁c₂c₃, le code de Morton est b₁c₁b₂c₂b₃c₃. Cette linéarisation préserve la localité spatiale : des points proches sur la courbe en Z sont spatialement proches en 2D. Le code de Morton d'un point est exactement le chemin de la racine à la feuille dans un quadtree PR encodé sous forme de chaîne binaire. Les systèmes de bases de données (par ex., DynamoDB, Google S2) utilisent les courbes de Morton ou de Hilbert pour indexer des données spatiales dans des arbres B 1D, obtenant des performances de requête équivalentes à celles d'un quadtree avec des structures d'index standard.

Les quadtrees peuvent-ils représenter des données spatiales non ponctuelles telles que des polygones ?

Oui — le quadtree de région stocke quelles cellules (pixels) sont « à l'intérieur » d'un polygone en subdivisant jusqu'à ce que les cellules soient entièrement à l'intérieur, entièrement à l'extérieur, ou à la limite de résolution (alors stockées comme partiellement couvertes). Les quadtrees vectoriels insèrent des segments de ligne ou des polygones en testant chaque niveau de subdivision pour une intersection. Stocker de grands polygones naïvement provoque une duplication à travers de nombreux nœuds ; les arbres R (Guttman, 1984) sont généralement préférés pour l'indexation de rectangles et de polygones en SIG car ils englobent étroitement les objets et évitent un stockage redondant multi-nœuds.

À propos de cette simulation

Cette simulation fait croître un quadtree point-région (PR) en direct pendant que vous dispersez, glissez ou peignez des points sur un canevas 2D. Chaque fois qu'une cellule feuille contient plus de points que la capacité actuelle, elle se divise en quatre quadrants égaux — NO, NE, SO et SE — autour de son propre point médian, en récursant jusqu'à ce que chaque cellule soit sous la capacité ou ait atteint une limite de profondeur fixe. Changer de mode vous permet de faire glisser un rectangle de requête de plage, de sonder pour un plus proche voisin, ou de mettre tous les points en mouvement pour observer le même arbre piloter la phase large de collision, avec des compteurs en direct comparant les nœuds visités à une recherche linéaire naïve.

🔬 Ce que cela montre

Des lignes de subdivision sont dessinées à mesure que les cellules se divisent, les points à l'intérieur d'une boîte de requête de plage active deviennent cyan, et la correspondance de plus proche voisin actuelle est mise en évidence en jaune avec son rayon de recherche dessiné comme un cercle. En mode Mouvement/collision, le voisinage de chaque point n'est vérifié que par rapport aux cellules proches plutôt qu'à chaque autre point, et les statistiques comparent les paires de candidats trouvées par l'arbre au nombre de paires qu'une vérification naïve de toutes les paires nécessiterait.

🎮 Comment utiliser

Le curseur Capacité par feuille (1–16, par défaut 4) définit combien de points une cellule contient avant de se diviser ; Vitesse d'animation (0,1×–3×) met à l'échelle le mouvement en mode Mouvement/collision. Six boutons radio de mode basculent entre ajouter/glisser, peindre un essaim, effacer, requête de plage, plus proche voisin et mouvement/collision ; Disperser 200, Effacer et Réinitialiser remplissent ou vident le canevas, et les cases à cocher Afficher la subdivision / Afficher les points / Afficher la fenêtre de requête basculent ce qui est dessiné.

💡 Le saviez-vous ?

Les quadtrees PR ont été introduits par Raphael Finkel et J. L. Bentley en 1974. Comme cette variante se divise toujours au point médian géométrique d'une cellule plutôt qu'aux coordonnées d'un point, sa profondeur maximale est fixée uniquement par la résolution — ici plafonnée à 10 niveaux dans le code, de sorte qu'aucune cellule ne peut se subdiviser indéfiniment même si de nombreux points se regroupent dans une petite zone.

Questions fréquemment posées

Comment ce quadtree décide-t-il quand diviser une cellule ?

Chaque cellule commence comme une seule feuille contenant tous ses points. Dès que le nombre de points d'une feuille dépasse la valeur du curseur Capacité par feuille, elle se divise en quatre quadrants enfants de taille égale à son propre point médian, redistribue ses points vers l'enfant qui les contient désormais, et devient un nœud interne. La division s'arrête une fois que la profondeur d'une cellule dépasse 10, même si elle contient encore plus de points que sa capacité.

Que change l'augmentation ou la diminution du curseur de capacité par feuille ?

Une faible capacité force les cellules à se diviser bien plus tôt, de sorte que l'arbre devient plus profond avec plus de feuilles et de nœuds internes pour le même ensemble de points — visible dans les statistiques Feuilles, Nœuds internes et Profondeur maximale. Une capacité élevée permet à chaque feuille de contenir plus de points avant de se diviser, produisant un arbre moins profond qui visite moins de nœuds par requête mais parcourt plus de points à l'intérieur de chaque feuille.

Comment le mode requête de plage se compare-t-il à une recherche linéaire ?

Faire glisser un rectangle en mode Requête de plage parcourt l'arbre depuis la racine, ne descendant que dans les quadrants enfants qui coupent le rectangle et en ignorant complètement le reste. La statistique Nœuds visités compte exactement combien de cellules ont été vérifiées de cette façon, tandis que Recherche linéaire affiche toujours le nombre total de points — l'écart entre les deux nombres est l'économie que l'arbre apporte par rapport à la vérification individuelle de chaque point.

Comment la recherche du plus proche voisin évite-t-elle de vérifier chaque point ?

Choisir une cible en mode Plus proche voisin recherche d'abord le quadrant enfant contenant le point pour obtenir une distance actuelle-meilleure initiale, puis ne revérifie que les quadrants frères dont le coin le plus proche possible est plus proche que cette meilleure distance — tout le reste est élagué. Le cercle jaune dessiné autour du point de requête marque la meilleure distance actuelle, et Nœuds visités indique combien de cellules ont réellement été examinées.

Que se passe-t-il en mode Mouvement/collision ?

Chaque point reçoit une vitesse et rebondit sur les bords du canevas, et à chaque image, le quadtree est reconstruit et utilisé pour exécuter une petite requête de plage autour de chaque point afin de trouver les candidats de collision proches, plutôt que de le comparer à chaque autre point. Les statistiques Résultat de la requête et Nœuds visités montrent les paires de candidats uniques trouvées par le quadtree, tandis que Recherche linéaire montre le total des paires qu'une vérification naïve de toutes les paires nécessiterait.

⚙ Sous le capot

Un quadtree subdivise récursivement le plan en quatre enfants. Regardez-le s'adapter à votre essaim de points et accélérer les requêtes de plage, de plus proche voisin et de collision — bien moins de nœuds visités que O(n).

Canvas 2DStructure de donnéesQuadtreeIndex spatialRequête de plage

3D · moteur de rendu Three.js / WebGL · cible 60 FPS · s'exécute entièrement côté client, sans installation

Qu'avez-vous trouvé ?

Ajouter les étapes de reproduction (facultatif)