11
votes

Générer de nouveaux polygones d'un polygone coupé (2D)

Je suis coincé avec ce petit problème et mon algorithme pour résoudre cela ne tient pas pour tous les cas. Est-ce que quelqu'un a une idée de savoir comment résoudre ce problème?

Voici un exemple de polygone:

exemple d'exemple http://img148.imageshack.us/img148/8804/poly.png

Description formelle

Nous avons une liste de points dans la commande CW définissant le polygone. Nous pouvons également interroger si un point est un point de coupe avec is_cut (p) , où p est un point donné. Maintenant, nous voulons calculer de nouveaux polygones causés par cette "coupe".

L'algorithme doit faire ceci:

entrée: {A, C1 , B, C4, C, C5, D, C6, E, C3, C2}

Sortie: {A, C1, C2} , < code> {b, c4, c3, f, c2, c1} , {d, c6, c5} , {e, c3, c4, c, c5, c6 }

ici mon algorithme actuel: xxx

Cet algorithme ne tienne pas si vous commenciez AT C ou f .


5 commentaires

Quand j'ai vu votre photo, j'ai enfin compris la sortie. Cependant, je ne pense pas, étant donné cette entrée, l'ordinateur peut en quelque sorte supposer de manière magique que les coordonnées C appartiennent tous ensemble. Je pense donc que cela formerait les coordonnées du polygone, vous avez également besoin d'une matrice d'entrée séparée spécifiant laquelle de ces indices sont les indices à couper. Plus logique serait: un polygone et 1 vecteur qui définit la ligne de coupe


Correct, j'ai calculé les points C_n avant, donc je peux fournir une fonction is_cut (p), qui formerait une telle liste {C1, ..., cn}, où n mod 2 == 0. Je suis désolé pour le Image, mais Stackoverflow ne me permet pas encore de poster des images :(.


J'ai aussi ajouté un algorithme pseudocode que j'ai utilisé pour le savoir.


hm ... cette image me rappelle quelque chose que je vois tous les jours dans le métro. (Pic) alloyfirms.ru/bank/5295_moscou.gif


@PAVEL: Ceci est ma carte de métro ECAMMANY.com/ny/subwaymap.gif


4 Réponses :


5
votes

Tout d'abord vous devez calculer quels segments de la ligne de coupe appartiennent à votre polygone interne de d'origine. C'est un problème classique, et sa solution est simple. Étant donné que vos points c1, c2, c3 ... c6 sont disposés le long de la ligne dans cet ordre exactement, puis segments C1-C2 , -c4 c3 etc appartiendront toujours de polygones internes (*).

Maintenant, nous pouvons construire algorithme récursif simple pour les polygones de coupe. Compte tenu de votre grand tableau d'entrée, {a, c1, b, c4, c, c5, d, c6, e, c3, f, c2}, commencez à tout point de polygone, par exemple, b ; ajouter à un tableau Résultat . Traverse le tableau d'entrée vers l'avant. Si vous rencontrez

  • pousser à un tableau noeud polygone habituelle , Résultat .
  • ck noeud, où k est impair , rechercher les c (k + 1) et maintenir déplacement de sa position.
  • ck noeud, où k est encore , rechercher les c (k-1) , sauter à sa position et garder traversant néanmoins en avant.

    Pour deux derniers cas, ajouter ces noeuds dans l'ordre que vous rencontrez à Résultat array. Ajouter ck noeud jeu cut , et ajouter un autre noeud ( c (k + 1) ou c (k-1) , selon ce que vous avez) dans un ensemble global fait .

    Si vous devez aller au-delà du dernier élément, circuit au premier élément du tableau d'entrée.

    Tôt ou tard, vous rencontrerez le nœud initial que vous traversions à partir. Maintenant, dans le Résultat array vous avez un polygone que vous avez coupé. Souviens toi. Répétez la procédure récursive, à partir de la position de chaque noeud qui appartient à cut ensemble et ne pas appartenir à l'économie mondiale fait < / em> ensemble.

    C'est la solution que je vois. Mais il est geomentry de calcul, donc il peut tourner un peu plus complexe qu'il n'y paraît.


    Pour notre exemple, commencer à partir de b :

    1. DONE = {} , commencer à partir de b . Après la première passe, vous obtenez Résultat = [b, c4, c3, f, c2, c1] , cut = {c4, c2 } , = {fait c3, c1} ; Recurse c4 et c2 noeuds.
    2. done = {c3;} c1 , commencer à partir de c4 (récursion de 1). Après ce passage, vous obtenez Résultat = [c4, c, c5, c6, e, c3, c4] , cut = {c5 , c3} , fait + = {c6, c4} ; Recurse c5 .
    3. done = {c3, c4 c1;}; c6 , commencer à partir de c2 (récursion de 1). Après ce passage, vous obtenez Résultat = [c2, a, c1] , cut = {c1} , fait + = {} c2 ; Ne pas récursif à c1 , car il est dans fait ensemble;
    4. done = {c3, c4 c1;; c6; c2} , commencer à partir de c5 (récursion de 2). Après ce passage, vous obtenez Résultat = [c5, d, c6] , cut = {c5} , fait + = {} c6 ; Ne pas récursif c5 , car il est dans fait ensemble;

      Voila - vous obtenez 4 polygones que vous avez besoin .


      (*) Notez qu'il exige une plus grande représentation « mathématique » de la ligne. Par exemple, si l'un des sommets du polygone est sur la ligne, il faut doubler le sommet, à savoir si c point a été un peu plus près du côté droit et sur la ligne rouge, la ligne aurait < code> [c1, c2, c3, c, c, c6] points sur elle, et l'ensemble de polygone serait [a, c1, b, c, c, c, d, c6, e , c3, f, c2] .

      Parfois (pas dans cet exemple), il peut conduire à la coupe des polygones "vides", comme [a, a, a] . Si vous ne les avez pas besoin, vous pouvez les éliminer à un stade avancé. Quoi qu'il en soit, il est la géométrie de calcul avec un nombre immense de cas à la frontière. Je ne peux pas les inclure tous dans une réponse ...


4 commentaires

Citation: ... Segments C1-C2, C3-C4 etc. appartiendra toujours à des internes du polygone ... , ne tiendra pas toujours. Par exemple, supprimez les points de coupe c4 et c5 et que c soit le point de coupe.


@Bart K., il n'y a aucune erreur dedans. Explication ajoutée.


Désolé, je ne voulais pas impliquer que tu avais tort. C'est juste que vous faites que cela sonne vraiment facile, alors qu'il y ait (comme vous le mentionnez vous-même) un peu de cas de coin difficiles, il faut rendre compte.


Superbe réponse! Génial que vous avez piétiné après que vous ayez expliqué quoi faire.



3
votes

Vous pouvez appliquer Weiler ATHERTON Coupure (efficacement de ce que Pavel suggère), mais Il y a une énorme mise en garde.

En raison d'erreurs de points flottants, l'algorithme d'écrêtage W / A est extrêmement difficile à faire fonctionner bien - dans des cas tels que la ligne de clipping traversant un sommet ou précisément le long d'un bord du polygone, l'algorithme peut devenir confus Quel "chemin" autour du périmiter du polygone il devrait suivre et il génère ensuite des résultats incorrects.


2 commentaires

Ce que je suggère peut être facilement étendu à la manipulation de tels cas, mais mon algorithme n'a rien à savoir sur l'arithmétique de point flottant, il traverse simplement les matrices données (qui ne nécessitent pas beaucoup de précision).


Ce qui est correct: "C'est une géométrie informatique avec un immense nombre de cas frontaliers" ou "[IT] peut être facilement étendu à la manipulation de tels cas"? Toute personne qui a tenté de mettre en œuvre ces méthodes peut vous dire que l'algorithme ci-dessus ne prend que quelques minutes à mettre en œuvre et beaucoup plus longtemps de travailler dans un sens généralisé et utile. Si vous apportez une seule décision erronée (facilement effectuée lorsque tout le monde sait que les "ordinateurs ne peuvent pas faire de maths") lors de la traversée de la hiérarchie de votre nœud, vous générerez des sorties incorrectes.



0
votes

1 Trouver le côté de chaque point est strong>

Choisissez un pont qui n'est pas sur la coupe (A par exemple) et définissez-le sur le côté gauche (il ne doit pas jouer à Actaly) P >

Lorsque vous passez des points sur la coupe, le côté du point que vous atteignez le changement. Donc, vous trouvez des points de gauche / droit. P>

problème est que vous devriez également considérer que l'ordre des points devrait être de manière prérogée. (dans le sens des aiguilles d'une montre, par exemple) p>

2 Démarrez à chaque intermédiaire de CX et aller une fois dans le sens horaire et dans le sens contraire des aiguilles d'une montre. STR> P>

pour chaque polygone que vous avez touché la mi-script dans une seule direction Une fois. p>

Si vous "débordez" c cela signifie que vous atteignez le polynome extérieur. Vous pourriez résoudre ce problème si vous définissez C0 et Cmax qui réside sur Polgon et que vous avez P>

input =  {a, c1, c0 ,c1, b, c4, c, c5, d, c6, c7, c6, e, c3, f, c2}


0 commentaires

0
votes

Le plus simple à mettre en œuvre est Sutherland-Hodgman . Le problème avec c'est qu'il laisse de petits rubans de zone zéro reliant les polys d'un côté de la ligne. Dans votre exemple, cela vous donnerait quelque chose comme:

{A C2 C3 E C6 C5 C C4 C1} et {B C1 C2 F C3 C6 D C5 C4}

Si vous pouviez vivre avec ceci ou déterminer comment les casser dans les morceaux que vous souhaitez, vous constateriez que le code qui faisait l'écrêtage réel serait aussi simple que possible.

La mise en œuvre nécessite simplement deux piles et une seule passe à travers les sommets de votre polygone. Sur chaque sommet, vous vérifiez si vous avez traversé la ligne depuis le sommet précédent. Si tel est le cas, calculez le point de croisement et poussez-le sur l'une des piles. Puis appuyez sur le nouveau sommet sur l'une des piles. Vraiment facile.


0 commentaires