Algorithme pour voir si deux voxels sont interconnectés

11

Je cherche un bon algorithme pour le problème suivant: Étant donné une grille 3D de voxels (qui peut être vide ou remplie), si je choisis deux voxels non adjacents, je veux savoir s'ils sont connectés les uns aux autres par d'autres voxels.

Par exemple (pour illustrer la situation en 2D), où # est un carré rempli:

  1 2 3
a # # #
b # #
c # # #

Si je choisis a3 et c3, je veux déterminer le plus rapidement possible s'ils sont connectés; s'il y a un chemin entre a3 et c3 à travers des pixels pleins. (La situation réelle est dans une grille de voxels 3D, bien sûr.)

J'ai regardé les algorithmes de remplissage et les algorithmes de recherche de chemin, mais je ne sais pas lequel choisir. Les deux font un travail inutile: le remplissage par inondation essaie de remplir tous les voxels, mais ce n'est pas nécessaire. Les algorithmes de recherche de chemin visent généralement à trouver le chemin le plus court, ce qui n'est pas non plus nécessaire. Je ne ai besoin de savoir s'il est un chemin.

Quel algorithme dois-je utiliser?

Edit: sur la base des commentaires, je pense qu'il faudrait ajouter ce qui suit: le contenu des voxels n'est pas connu à l'avance, et aussi, l'algorithme est nécessaire pour détecter si la suppression (le vidage) d'un voxel entraînerait la rupture du groupe de voxels en deux ou plusieurs petits groupes.

Bram Vaessen
la source
Dans votre exemple, un chemin valide de a3 à c3 serait-il le suivant c3->c2->b2->a2->a3:?
c'est exact
Bram Vaessen

Réponses:

12

Un * fonctionnerait très bien. La recherche de chemin est ce que vous voulez, trouver le chemin le plus court est tout aussi rapide (ou plus rapide) que de trouver n'importe quel chemin. Dans cette situation, A * est probablement le plus approprié étant donné que vous avez un point de départ et un point d'arrivée. cela signifie que vous avez l'heuristique ajoutée pour accélérer la recherche.

Avec A *, le premier chemin que vous trouvez est généralement le plus court, il ne fait donc pas de travail supplémentaire après avoir déjà trouvé un chemin.

entrez la description de l'image ici

Pour quelques optimisations, consultez ma réponse ici .

MichaelHouse
la source
On dirait qu'il tire vraiment vers l'avant jusqu'à ce qu'il touche ce mur, puis il se glisse en quelque sorte
GameDev-er
1
@ GameDev-er Oui, c'est à cause de l'heuristique. S'il n'y avait pas d'obstacle, ce serait une recherche très rapide, presque une ligne droite.
MichaelHouse
Avec un meilleur tri des nœuds, cela élargirait d'abord le chemin le plus proche du nœud final. Si vous disposez d'une structure de données rapide pour classer les nœuds, triez-les par distance de la cible pour le chemin le plus direct.
MichaelHouse
9

Si vous êtes prêt à effectuer un prétraitement et à consommer le coût de stockage, alors le partitionnement des voxels en groupes connectés au moment de la construction donne une réponse évidente à `` y a-t-il un chemin du tout ''. Il y a un chemin entre deux voxels s'ils sont dans le même groupe. Le problème avec cela est évidemment que vous devez stocker des informations de groupe quelque part, et cela dépend de la disposition de vos données. Si vous stockez une liste simple, vous pouvez simplement la diviser en plusieurs listes, une pour chaque groupe connecté spatialement. Si vous vous organisez dans une sorte de BVH, alors vous pourriez probablement obtenir des efficacités raisonnablement bonnes si vous pouvez dire "tous les voxels dans ce nœud et ci-dessous appartiennent au groupe X".

Alternativement, vous pouvez effectuer une pré-partitionnement spatial et stocker un ensemble plus petit de voxels «concentrateurs» pour chaque groupe connecté. Ensuite, vous pouvez rechercher un chemin à partir de vos voxels source et cible vers leur voxel concentrateur le plus proche, ce qui devrait être beaucoup plus court / moins cher à calculer. Si vous pouvez trouver un chemin d'un voxel à un voxel concentrateur, alors le voxel fait partie du groupe du voxel concentrateur. Avec une sélection intelligente de ces voxels de concentrateur, vous pouvez minimiser le nombre de traversées de chemin. Par exemple, une sphère peut avoir un seul voxel central en son centre, mais un groupe long et mince peut avoir un voxel central tous les X voxels sur sa longueur. Si vos voxels source et cible se trouvent à l'une ou l'autre extrémité de la longueur, ils n'ont qu'à parcourir au plus X voxels pour trouver un concentrateur, et même s'il peut y avoir un grand nombre de voxels entre le début et la fin de la longueur,

Tout dépend de la pathologie de vos groupes de voxels: si vous vous attendez à un grand nombre de petits groupes déconnectés, l'augmentation des coûts de stockage va largement contrebalancer les performances de la recherche de chemins. Si vous vous attendez à relativement peu de groupes connectés mais à des topologies étranges, la recherche de chemin naïve peut être extrêmement coûteuse et le coût de stockage et la recherche de chemin minimale sont une option beaucoup moins chère.

MrCranky
la source
1
C'est la bonne réponse, mais pour la mettre en œuvre efficacement, elle ne doit pas être stockée sous forme de liste. Ajoutez un pointeur à chaque voxel qui pointe vers son "voxel représentatif", que vous définissez à l'aide de l'algorithme union-find. Il s'agit d'un coût de stockage constant par voxel, et fondamentalement linéaire dans le nombre d'arêtes pour le coût de calcul.
Neil G
Des idées intéressantes, mais deux choses pourraient compliquer la situation. La première est que le contenu de la grille de voxels n'est pas connu à l'avance, donc pour faire des voxels de concentrateur, j'aurais également besoin d'un algorithme qui puisse déterminer quels voxels devraient être des concentrateurs.
Bram Vaessen
1
Le deuxième problème est que l'algorithme est nécessaire juste après la suppression d'un voxel, pour déterminer si le groupe dont il faisait partie est divisé en petits groupes en raison de la suppression de ce voxel.
Bram Vaessen
@BramVaessen Si vous recherchez toutes les relations d'interconnectivité par paire - et en particulier, si les groupes «se séparent» - alors c'est une question quelque peu différente de la simple accessibilité (bien que l'accessibilité soit la façon la plus simple de s'y prendre); J'encourage à ajouter plus de détails sur ce que vous recherchez spécifiquement à la question d'origine, car cela pourrait permettre de meilleures réponses au «problème derrière la question».
Steven Stadnicki
Pour le garder propre, j'ai posé mon problème initial dans une autre question ici gamedev.stackexchange.com/questions/50953/…
Bram Vaessen
4

Je ne connais pas très bien les voxels, mais j'imagine que vous pourriez obtenir de très bonnes performances en utilisant un algorithme de recherche de premier ordre tel que A *. Le problème avec l'utilisation de A * dans ce cas est que l'heuristique que l'on utiliserait normalement est conçue pour prioriser la recherche du chemin le plus court et pas seulement de «n'importe quel chemin» aussi rapidement que possible.

Vous pouvez avoir de la chance en utilisant une autre heuristique qui étend moins de nœuds tels que

f (p) = g (p) + w (p) * h (p)

où w> = 1. vous diminuez la valeur de «w» plus vous vous rapprochez de l'objectif, donnant ainsi une priorité plus élevée au coût du chemin «g» plus vous vous rapprochez du voxel que vous recherchez.

J'espère que ça aide!

Matthew R.
la source