Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1171 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Remplissage de polygônes - help!!

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

Remplissage de polygônes - help!!

n°699853
gustifotz
Posté le 15-04-2004 à 09:45:16  profilanswer
 

Salut les gens,
 
Suis actuellement confronté à un chti problème avec un projet que je développe sous Visual C++ 6.0 : En fait l'idée est simple, je cherche à coder un outil genre "remplissage" comme dans paint, mais comme je débute, je ne connais pas toutes les possibilités offertes par le C++ (mais ca va venir...  :) )  
Pour l'instant, je m'entraîne avec une ellipse de contour noir. J'utilise la fonction CDC::GetPixel pour détecter les contours de l'ellipse et remplir un tableau avec des 1 et des 0 : 1 si présence d'un pixel noir, 0 sinon. Ensuite, et c'est là que ca coince  :D , j'aimerais remplacer par des 1 une chaîne de 0 placée entre deux chaînes de 1. Par exemple :
 
00000011111110000000000011111111110000000000 deviendrait
00000011111111111111111111111111110000000000
 
ou
 
00000000010000000000000010000000000000000000 deviendrait
00000000011111111111111110000000000000000000
 
Bref vous voyez le truc. Et ben c'est là que ca coince  :( .
Est-ce qu'il y aurait une âme charitable pour me donner des idées ou au moins pour me dire si ma manière de procéder peut être la bonne ou si elle est à revoir??
Ma vie est entre vos mains  ;) Merci par avance.

mood
Publicité
Posté le 15-04-2004 à 09:45:16  profilanswer
 

n°699929
Joel F
Real men use unique_ptr
Posté le 15-04-2004 à 10:53:25  profilanswer
 

parcourt ton tableau ligne par ligne en cherchant les 1
des que tu en trouves un, remplis les cases suivantes avec des 1 jusqu'au prochain un, et continue jusqu'a la fin de la ligne
itere sur toutes les lignes.

n°699940
gustifotz
Posté le 15-04-2004 à 11:03:27  profilanswer
 

Oui, c'est l'idée que j'avais eue aussi mais pour le cas d'une ligne qui ressemblerait à :
0000000001100000000000000011111100000 Je détecte le premier 1 et je mets des 1 jusqu'au prochain 1, donc rien ne sera modifié...
Par contre j'arrive à détecter le dernier 1 d'une série de 1 :
if (tab[k] >= tab[k-1] && tab[k] > tab[k+1])
et le premier 1 d'une série de 1 :
if (tab[k] > tab[k-1] && tab[k] >= tab[k+1])
Mais rien n'y fait. Le problème c'est je peux dire que je mets des 1 à partir du dernier 1 de la série de 1 (fiou... compliqué...) et zou toute la fin de la ligne passera à 1...
J'ai essayé plein de trucs, genre utiliser des compteurs pour savoir combien de fois on est passé de 0 à 1 et de 1 à 0 et réagir en conséquence. Mais ca morch pô...
Merci pour ta réponse. Reste cool avec les castors.

n°699959
cricri_
Posté le 15-04-2004 à 11:11:40  profilanswer
 

Bah là faut faire une vulgaire machine à état avec un switch case parceque les if machin c'est vraiment pas adapté à ce genre de pb.
 
genre tu démarres en etat DETECTION, une fois le front descendant ( 1->0) détecté et bien tu passes à l'etat REMPLISSAGE jusqu'à la détection front montant ( 0-> ).
 

n°699986
gustifotz
Posté le 15-04-2004 à 11:34:15  profilanswer
 

Oui je n'avais pas pensé à cette solution, mais quoi qu'il en soit je vais avoir un pb avec le deuxième front descendant. Après le deuxième front descendant, je vais repasser en mode REMPLISSAGE et c'est un comportement qui n'est pas souhaitable...
Bon j'essaie, merci pour ta réponse.

n°699990
cricri_
Posté le 15-04-2004 à 11:36:24  profilanswer
 

ok, il suffit de rajouter une étape je pense

n°699991
jeoff
Posté le 15-04-2004 à 11:36:47  profilanswer
 

cricri_ a écrit :

Bah là faut faire une vulgaire machine à état avec un switch case parceque les if machin c'est vraiment pas adapté à ce genre de pb.
 
genre tu démarres en etat DETECTION, une fois le front descendant ( 1->0) détecté et bien tu passes à l'etat REMPLISSAGE jusqu'à la détection front montant ( 0-> ).
 


 
je plussoie, en gros, tant que tu as des 1, tu ne fait rien (front montant), dès que tu as des 0 tu cherches le 1er 1 qui apparait et en attendant de le trouver tu remplaces par des 1.
 

n°699995
jeoff
Posté le 15-04-2004 à 11:37:55  profilanswer
 

gustifotz a écrit :

Oui je n'avais pas pensé à cette solution, mais quoi qu'il en soit je vais avoir un pb avec le deuxième front descendant. Après le deuxième front descendant, je vais repasser en mode REMPLISSAGE et c'est un comportement qui n'est pas souhaitable...
Bon j'essaie, merci pour ta réponse.


 
si tu raisonne ligne par ligne ça doit le faire non ?

n°700005
gustifotz
Posté le 15-04-2004 à 11:44:44  profilanswer
 

Ben suis pas sûr, sur une ligne il y a 2 fronts montant et 2 fronts descendant. Faudrait que je rajoute un compteur de fronts descendants, ouaip, allez je vais essayer ca...

n°700023
cricri_
Posté le 15-04-2004 à 11:58:25  profilanswer
 

Il suffit d'avoir une etape ATTENTE fin de ligne

mood
Publicité
Posté le 15-04-2004 à 11:58:25  profilanswer
 

n°700079
nico168
Posté le 15-04-2004 à 13:23:26  profilanswer
 

imaginons qu'une ligne soit comme ca :
0000000000100000000000
donc a priori, il n'y a rien a remplir, j'ai l'impression que vos propositions ne marche pas

n°700149
jeoff
Posté le 15-04-2004 à 14:05:12  profilanswer
 

nico168 a écrit :

imaginons qu'une ligne soit comme ca :
0000000000100000000000
donc a priori, il n'y a rien a remplir, j'ai l'impression que vos propositions ne marche pas


 
[:ddr555] effectivement c'est gênant :p
 
Je sais pas comment il lit son image mais si il peut, il a qu'a le faire en 2 passes. 1 pour la lecture et une pour l'écriture si nécessaire non :??:


Message édité par jeoff le 15-04-2004 à 14:06:52
n°700169
gustifotz
Posté le 15-04-2004 à 14:25:32  profilanswer
 

Bon, j'ai trouvé une autre méthode, peut-être un peu moins contraignante, à voir...
Pour chaque pixel, je teste dans la ligne correspondante s'il existe un pixel noir à sa gauche et un pixel noir à sa droite. Test idem pour la colonne. Si les 4 tests sont positifs, le pixel est à l'intérieur de mon ellipse et zou je le colore.
Pb : Pour chaque pixel, j'effectue 4 tests, j'ai peur que ca mouline un peu longtemps.
Bon je code et je vous dis si ca marche ou si ca ne marche pas.
En attendant les bonnes idées sont tjs les bienvenues... :)

n°700170
Moktar1er
No one replies...
Posté le 15-04-2004 à 14:26:06  profilanswer
 

et un truc comme ça?
 

Code :
  1. flag = tab[0]
  2. pour i de 1 à taille(tab)
  3.   flag = flag XOR tab[i]
  4.   tab[i] = flag OR tab[i]

n°700176
nico168
Posté le 15-04-2004 à 14:28:39  profilanswer
 

plus generalement, est ce qu'une ligne peut suffir pour savoir comment la remplir ?
je m'explique
imaginons que l'ont tombe sur une ligne comme cela :
000000100000100001000
je rempli quoi ? du 1er au 2eme ? du 2eme au 3eme ?
ben ca depend de se que la ligne represente (le 1er 1 peut etre un sommet du polygone ou un point d'un coté)
a mon avis decouper par ligne ne permet par de resoudre ce pb.

n°700183
nico168
Posté le 15-04-2004 à 14:33:31  profilanswer
 
n°700214
jeoff
Posté le 15-04-2004 à 15:00:14  profilanswer
 

gustifotz a écrit :

Bon, j'ai trouvé une autre méthode, peut-être un peu moins contraignante, à voir...
Pour chaque pixel, je teste dans la ligne correspondante s'il existe un pixel noir à sa gauche et un pixel noir à sa droite. Test idem pour la colonne. Si les 4 tests sont positifs, le pixel est à l'intérieur de mon ellipse et zou je le colore.
Pb : Pour chaque pixel, j'effectue 4 tests, j'ai peur que ca mouline un peu longtemps.
Bon je code et je vous dis si ca marche ou si ca ne marche pas.
En attendant les bonnes idées sont tjs les bienvenues... :)


 
tu risque aps de colorer trop de pixels par hasard ???
 
Je sais pas si tu lis ton image de gauche à droite ou de bas en haut mais 2 test suffisent pour savoir si tu est dans ta zone.
 
Exemple. Tu parcours ton image comme tu lis un livre --> gauche>droite et haut>bas.
Teste si ton pixel courant est blanc à chaque fois. Si oui c'est bon, sinon il faut passer en mode Remplissage/Arret Remplissage selon ce que tu faisait avant de rencontrer ce pixel noir
Il suffit de tester si le pixel précédent gauche était noir et si le pixel précédent haut était noir. Si c'est le cas tu colore le pixel courant et tu reteste avec celui de droite, dans ce cas comme tu viens de colorer celui de gauche, il ne te reste plus qu'à tester le pixel du haut.
 
Et ainsi de suite.
 
Pour chaque ligne, si tu doit économiser le temps de calcul,tu teste gauche et haut. Lorsque tu rempli les 2 conditions, tu rempli le pixel courant et tu passe en mode test haut uniquement tant que test haut est vrai. Si test haut passe a faux, tu repasse en mode test gauche et test haut et ainsi de suite.
 
J'espère que je me suis fait comprendre sinon je tenterai un dessin ;).


Message édité par jeoff le 15-04-2004 à 15:04:33
n°700242
gustifotz
Posté le 15-04-2004 à 15:18:32  profilanswer
 

Bon c'est la super honte!! Je n'arrive pas à créer un tableau de deux dimensions (400 * 250) avec new. Si si je vous assure... Bon je vais me cacher sous le bureau en attendant vos moqueries... :)

n°700245
jeoff
Posté le 15-04-2004 à 15:20:34  profilanswer
 
n°700251
gustifotz
Posté le 15-04-2004 à 15:23:39  profilanswer
 

Ok Joeff, merci, ca a l'air pas mal. Je teste ca dès que je m'en suis orti avec mes tableaux 2D... (ho c'te honte)

n°704961
gustifotz
Posté le 21-04-2004 à 14:19:23  profilanswer
 

Ok les gens,
J'ai finalement trouvé une solution à mon problème de remplissage de polygônes :sweat: . Aux oubliettes les tableaux deux dimensions et les 1 et les 0 :) . Le programme suivant analyse pour chaque pixel de la figure s'il existe un pixel noir à la gauche du pixel en question, en bas, à sa droite et en haut. Si tel est le cas, le pixel est coloré en rouge, sinon on passe au pixel suivant.
Ca fonctionne plutôt bien sauf pour les formes un peu exotiques, mais pour tout ce qui est carré, rectangle, triangle, trapèze, cercle, ellipse, ... pas de problème.

Code :
  1. void ChangeColor (int picwidth, int picheight, CDC* pDC)
  2. {
  3. int left, down, right;
  4. for (int i = 1; i <= picheight; i++)
  5. {
  6.  for (int j = 1; j <= picwidth; j++)
  7.  {
  8.   if (pDC->GetPixel (j, i) != RGB (0, 0, 0))
  9.   {
  10.    for (int k = j-1; k >= 1; k--)
  11.    {
  12.     if (pDC->GetPixel (k, i) == RGB (0, 0, 0))
  13.     {
  14.      left = 1;
  15.      break;
  16.     }
  17.     else
  18.      left = 0;
  19.    }
  20.    if (left == 1)
  21.    {
  22.     for (int l = i+1; l <= picheight; l++)
  23.     {
  24.      if (pDC->GetPixel (j, l) == RGB (0, 0, 0))
  25.      {
  26.       down = 1;
  27.       break;
  28.      }
  29.      else
  30.       down = 0;
  31.     }
  32.    }
  33.    if (left == 1 && down ==1)
  34.    {
  35.     for (int m = j+1; m <= picwidth; m++)
  36.     {
  37.      if (pDC->GetPixel (m, i) == RGB (0, 0, 0))
  38.      {
  39.       right = 1;
  40.       break;
  41.      }
  42.      else
  43.       right = 0;
  44.     }
  45.    }
  46.    if (left == 1 && down == 1 && right == 1)
  47.    {
  48.     for (int n = i-1; n >= 0; n--)
  49.      if (pDC->GetPixel (j, n) == RGB (0, 0, 0))
  50.       pDC->SetPixel (j, i, RGB (255, 0, 0));
  51.    }
  52.   }
  53.  }
  54. }
  55. }


Par contre le gros inconvénient, c'est la vitesse d'exécution  :( . J'ai le temps d'aller boire trois café pendant le traitement d'une figure de la taille de mon écran. Y aurait-il une solution plus rapide??

n°704971
skeye
Posté le 21-04-2004 à 14:23:59  profilanswer
 

gustifotz a écrit :


Par contre le gros inconvénient, c'est la vitesse d'exécution  :( . J'ai le temps d'aller boire trois café pendant le traitement d'une figure de la taille de mon écran. Y aurait-il une solution plus rapide??  


Tu bosses directement à l'écran là non? (je connais pas grand-chose aux api microsoft de ce coté...).
Si c'est le cas le mieux c'est de récupérer ton image en ram, la traiter, puis la rebalancer vers l'écran.


Message édité par skeye le 21-04-2004 à 14:24:10
n°704976
Moktar1er
No one replies...
Posté le 21-04-2004 à 14:26:12  profilanswer
 

skeye> +1
 
sinon... un algo comme le floodfill ça serait pas mieux? ils sont gros tes polygones?

n°705040
gustifotz
Posté le 21-04-2004 à 14:55:44  profilanswer
 

Floodfill?? Sais pas trop ce que c'est...  :(  
En fait, à terme, ce ne seront plus des polygônes mais des patates mi-ellipses mi-n'importe quoi, et concentriques. Ce sont des figures qui prennent la taille de mon écran à peu près... Un fort bel écran ma foi.
Plus sérieusement, je pense que l'idée du traitement en Ram puis de l'affichage du résultat est une voie que je vais explorer de ce pas  :) .
Merci pour vos tips  ;) .

n°705046
Ace17
Posté le 21-04-2004 à 14:58:43  profilanswer
 

Pourquoi tu fais pas ca pseudo-récursivement?
Tu prends ton point a l'intérieur, et tu vérifies ses voisins, et pour chacun d'eux tu réiteres?

n°705048
Moktar1er
No one replies...
Posté le 21-04-2004 à 14:59:43  profilanswer
 

gustifotz a écrit :

Floodfill?? Sais pas trop ce que c'est...  :(  
En fait, à terme, ce ne seront plus des polygônes mais des patates mi-ellipses mi-n'importe quoi, et concentriques. Ce sont des figures qui prennent la taille de mon écran à peu près... Un fort bel écran ma foi.
Plus sérieusement, je pense que l'idée du traitement en Ram puis de l'affichage du résultat est une voie que je vais explorer de ce pas  :) .
Merci pour vos tips  ;) .


 
le floodfill c'est tout con, mais gourmand [:spamafote]
un exemple d'algo:
 

Code :
  1. floodfill(x,y,couleur_origine,couleur_destination){
  2. if( pixels(x,y) == couleur_origine ){
  3. pixels(x,y) = couleur_destination;
  4. floodfill(x-1,y,couleur_origine,couleur_destination);
  5. floodfill(x+1,y,couleur_origine,couleur_destination);
  6. floodfill(x,y-1,couleur_origine,couleur_destination);
  7. floodfill(x,y+1,couleur_origine,couleur_destination);
  8. }
  9. }


 
et là je n'ai fais que la version la moins gourmande (sur les 4 voisins).
tu peux faire ta recursivité sur les 8 voisins, c'est plus rapide mais encore plus gourmand.
pourquoi gourmand? car récursif...

n°705063
gustifotz
Posté le 21-04-2004 à 15:07:39  profilanswer
 

Qu'est-ce que tu entends par gourmand?
Je vais essayer d'implémenter ca, ca m'a l'air pas mal est pas trop dur... Comme je suis carrément chaud, je vais direct m'attaquer aux huit voisins :).
Au boulot... Je vous tiens au courant.

n°705068
skeye
Posté le 21-04-2004 à 15:09:28  profilanswer
 

gustifotz a écrit :

Qu'est-ce que tu entends par gourmand?


en mémoire.

n°705069
Moktar1er
No one replies...
Posté le 21-04-2004 à 15:10:24  profilanswer
 

skeye a écrit :

en mémoire.


 
:D
j'ai jamais réussi à le faire tourner sur des formes de plus de 600x400 de boîte englobante  :lol:

n°705072
skeye
Posté le 21-04-2004 à 15:12:03  profilanswer
 

moktar1er a écrit :

:D
j'ai jamais réussi à le faire tourner sur des formes de plus de 600x400 de boîte englobante  :lol:  


ah oué quand même...[:joce]

n°705074
Moktar1er
No one replies...
Posté le 21-04-2004 à 15:14:19  profilanswer
 

le problème vient surtout de la pile d'appel qui viens vite à saturation
j'ai eu beau jongler avec les tailles de pile et de tas, à chaque fois je me suis retrouvé coincé...
par contre, sur des petites formes ça roxxe méchamment

n°705076
skeye
Posté le 21-04-2004 à 15:14:55  profilanswer
 

moktar1er a écrit :

le problème vient surtout de la pile d'appel qui viens vite à saturation
j'ai eu beau jongler avec les tailles de pile et de tas, à chaque fois je me suis retrouvé coincé...
par contre, sur des petites formes ça roxxe méchamment


faut le faire en lisp!:o

n°705078
Moktar1er
No one replies...
Posté le 21-04-2004 à 15:15:46  profilanswer
 

bah tiens, fais nous un bench C/lisp, toi qui a tout plein de temps :D

n°705079
gustifotz
Posté le 21-04-2004 à 15:16:30  profilanswer
 

ah ouais, quand même...  :ouch:  
Bon, pas grave, je tente... On verra bien ce ca donne  :D .

n°705081
skeye
Posté le 21-04-2004 à 15:16:56  profilanswer
 

moktar1er a écrit :

bah tiens, fais nous un bench C/lisp, toi qui a tout plein de temps :D


J'ai pas touché au lisp depuis la maitrise (ou licence même p-e...) et j'ai pas l'intention de changer quoi que ce soit à cet état de fait![:joce]

n°705083
Moktar1er
No one replies...
Posté le 21-04-2004 à 15:18:01  profilanswer
 

gustifotz a écrit :

ah ouais, quand même...  :ouch:  
Bon, pas grave, je tente... On verra bien ce ca donne  :D .


 
méfies toi des résultats au fait
ce n'est pas parceque ça ne plante pas que ça marche ;)

n°705085
skeye
Posté le 21-04-2004 à 15:19:02  profilanswer
 

moktar1er a écrit :

méfies toi des résultats au fait
ce n'est pas parceque ça ne plante pas que ça marche ;)


'tention à la connexité des contours, je suppose! ;)

n°705088
Moktar1er
No one replies...
Posté le 21-04-2004 à 15:20:20  profilanswer
 

skeye a écrit :

'tention à la connexité des contours, je suppose! ;)


 
oui entre autres
sinon j'ai pu voir des choses bizarres justement à cause de la perte de la pile d'appels (récursivité infinie alors que le test d'arrêt est forcément vrai, appel de fonctions non désirées etc.)

n°705973
gustifotz
Posté le 22-04-2004 à 14:21:17  profilanswer
 

Bon ben voilà, c'est la fête  :pt1cable: , merci beaucoup pour le coup de pouce  :jap: . J'ai implémenté ce fameux floodfill, en effectuant une récurrence sur les 4 voisins les plus proches, et je dois avouer que le résultat est stupéfiant  :ouch: . Même avec des figures complexes c'est nickel.
Si j'effectue une récurrence sur les 8 voisins les plus proches, je me retrouve avec des effets de bord indésirables...  :( Mais bon, la vitesse atteinte avec 4 voisins est déjà largement satisfaisante  :o . J'ai rajouté une ch'tite boucle pour localiser le premier pixel à partir duquel lancer le floodfill, c'est le premier pixel qui a un pixel noir à sa gauche et un pixel noir juste au-dessus. Il se trouve alors dans la figure à colorier.
Voici le prog final, qui tient en qques lignes, et qui fonctionne effectivement (testé avec MS Visual C++ 6.0) :

Code :
  1. void FloodFill (int x, int y, CDC* pDC)
  2. {
  3. if (pDC->GetPixel (x, y) == RGB (255, 255, 255))
  4. {
  5.  pDC->SetPixel (x, y, RGB (255, 0, 0));
  6.  FloodFill (x+1, y, pDC);
  7.  FloodFill (x-1, y, pDC);
  8.  FloodFill (x, y+1, pDC);
  9.  FloodFill (x, y-1, pDC);
  10. }
  11. }
  12. void ChangeColor (int picwidth, int picheight, CDC* pDC)
  13. {
  14.         int x, y;
  15. for (int i = 1; i <= picwidth; i++)
  16. {
  17.  for (int j = 1; j <= picheight; j++)
  18.  {
  19.   if (pDC->GetPixel (j-1, i) == RGB (0, 0, 0) &&
  20.    pDC->GetPixel (j, i-1) == RGB (0, 0, 0))
  21.   {
  22.    x = i;
  23.    y = j;
  24.    break;
  25.   }
  26.  }
  27. }
  28. FloodFill (x, y, pDC);
  29. }


 
Par contre, dès que je veux traiter des figures un peu plus grandes, ca coince... Y aurait-il une manip à effectuer sur windows qui pourrait m'aider, genre augmenter la taille de la mémoire virtuelle??
Ou sinon j'ai toujours la possibilité de faire le traitement en mémoire et d'afficher le résultat une fois le traitement terminé.
Quoi qu'il en soit, un grand MERCI pour vos conseils, ca fait plaisir, je reviendrai tiens!!  :D

n°705976
skeye
Posté le 22-04-2004 à 14:24:24  profilanswer
 

gustifotz a écrit :


Par contre, dès que je veux traiter des figures un peu plus grandes, ca coince... Y aurait-il une manip à effectuer sur windows qui pourrait m'aider, genre augmenter la taille de la mémoire virtuelle??


 
C'est le pb de la récursivité...pasgrand chose à faire!:/
 

gustifotz a écrit :


Ou sinon j'ai toujours la possibilité de faire le traitement en mémoire et d'afficher le résultat une fois le traitement terminé.


De toute manière c'est conseillé quelle que soit ta méthode ensuite.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Remplissage de polygônes - help!!

 

Sujets relatifs
help me !!!help des noms de serveurs gratuit please
[help] est ce qu il existe des templates simples de sites en php?Help (je n'arrive pas à selectionner une ligne dans ma table)
help ! seekg et ifstream , ça marche pas !Help pour compiler un programme *non limité dans le temps*
HELP ! création d'une mailing list à partir d'un site web ...?Help!! [boucle avec select]
[PHP] Help changement imageMasterMind en JAVASCRIPT. Help !
Plus de sujets relatifs à : Remplissage de polygônes - help!!


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR