1

je cherche à clipper un polygone avec un rectangle representant l'ecran le polygone est tracé avec une fonction g_polyline(x1,y1,x2,y2,x3,y3,x1,y1) ,ou le dernier point est le 1er afin de fermer le polygone; l'ecran est defini par xmin, xmax, ymin, ymax
j'utilise l'algorithme de Cohen Sutherland qui clippe chaque segment du polygone.

les points du polygone sont bien clippés mais j'obtient une structure formée de segments non fermés et donc impropre au remplissage. comme sur l'image :
clipping.jpg

j'ai essayé avec plusieurs tests de créer les points neccessaires à tous les cas de figures mais la liste de tests devient vite impresionnante pour un "simple" clipping 2D.
Par exemple,avec quelques tests je peux resoudre le clipping du polygone A de l'image en dessous mais pas du polygone B.
Image6.jpg

Quelqu'un connait un autre algorithme et sa façon de l'utiliser? Une idée?
(je precise qu'il ne s'agit pas de clipper au remplissage mais bien avant d'appeller la fonction, et donc d'envoyer les bonnes coordonnées à g_polyline(x1,y1,x2,y2,x3,y3,x1,y1) )

2

j'avais oublié la source (c'est en java, je l'ai converti vite fait en C, il reste surement des erreurs) :    public int codecohen(i)  {       int code = 0;       double abs = Pt2D_x[i];       if(abs < xmin) {code=code+1;}    // on ajoute 0001 en binaire pour la partie gauche hors écran       if(abs > xmax) {code=code+2;}  // on ajoute 0010 en binaire pour la partie droite hors écran       double ord = Pt2D_y[i];       if(ord > ymax) {code=code+4;}  // on ajoute 0100 en binaire pour la partie basse hors écran       if(ord < ymin) {code=code+8;}    // on ajoute 1000 en binaire pour la partie haute hors écran       return code; // ainsi, on obtient le code de la région du point (exemple : haut et droite = 1010)    } // codecohen for (var i=0;i<nb_de_points;i++)      {      int tracesegment=true;      int pt1=inVAL+i;      int pt2=pt1+1;      if (i==nb-1){pt2=inVAL}//on prend le dernier point avec le premier pour fermer la face      var codecohenp1=codecohen(pt1);//on test la position des points      var codecohenp2=codecohen(pt2);      tx1=Pt2D_x[pt1];      ty1=Pt2D_y[pt1];      tx2=Pt2D_x[pt2];      ty2=Pt2D_y[pt2];       /*Algorithme du Clipping avec le codage de Cohen Sutherland       (permet de ne pas dessiner ce qui est hors de l'écran :        au dessus, en dessous, à droite, et à gauche de la partie visible)       -Si la totalité du segment est hors de l'écran, on ne dessine rien.       -Si l'un des deux points du segment est hors de l'écran,       on le remplace par l'intersection avec le bord de l'écran.       -Si les 2 points sont hors de l'écran, mais qu'il est possible       qu'une partie du segment soit dedans, on les remplace par       les intersections avec les bords de l'écran, puis on vérifie       que celles-ci sont bien au final dans l'écran, sinon on ne trace rien.       Le code de Cohen Sutherland en lui même,permet de savoir dans quelle zone se situe le point.*/       if((codecohenp1 & codecohenp2) != 0) {tracersegment=false;}       if(tracersegment) {          if((codecohenp1 & 1) == 1 && tx1<xmin) {ty1=ty1-tx1*(ty2-ty1)/(tx2-tx1); tx1=xmin;}          if((codecohenp1 & 2) == 2 && tx1>xmax) {ty1=ty1+(800-tx1)*(ty2-ty1)/(tx2-tx1); tx1=xmax;}          if((codecohenp1 & 4) == 4 && ty1>ymax) {tx1=tx1+(600-ty1)*(tx2-tx1)/(ty2-ty1); ty1=ymax;}          if((codecohenp1 & 8) == 8 && ty1<ymin) {tx1=tx1-ty1*(tx2-tx1)/(ty2-ty1); ty1=ymin;}          if((codecohenp2 & 1) == 1 && tx2<xmin) {ty2=ty2-tx2*(ty1-ty2)/(tx1-tx2); tx2=xmin;}          if((codecohenp2 & 2) == 2 && tx2>xmax) {ty2=ty2+(800-tx2)*(ty1-ty2)/(tx1-tx2); tx2=xmax;}          if((codecohenp2 & 4) == 4 && ty2>ymax) {tx2=tx2+(600-ty2)*(tx1-tx2)/(ty1-ty2); ty2=ymax;}          if((codecohenp2 & 8) == 8 && ty2<ymin) {tx2=tx2-ty2*(tx1-tx2)/(ty1-ty2); ty2=ymin;}       }       if(tx1<xmin || tx1>xmax || ty1<ymin || ty1>ymax || tx2<xmin || tx2>xmax || ty2<ymin || ty2>ymax) tracersegment = false;       //Maintenant, on trace uniquement si c'est nécessaire       if(tracersegment)      {      if (tx1==pointx[t-1] && ty1==pointy[t-1]) //pour eviter les doubles           {           pointx[t]=tx2;     pointy[t]=ty2;     t++;           }      else           {//rempli le tableau des points du polygone clippé           pointx[t]=tx1;     pointy[t]=ty1;     t++;           pointx[t]=tx2;     pointy[t]=ty2;     t++           }      //drawLine((int)tx1,(int)ty1,(int)tx2,(int)ty2);//pour verifier }

3

Soit ton cas B:
+----------------------------------+
|                     [7]|[/7]            |
|                     [7]|[/7]            |
|                     [7]|[/7]            |
|                     [7]|[/7]            |
|                     [7]|[/7]            |
|                     [7]|[/7]            |
+----------------------------------+


Tu dois relier les 2 points de ton polygône auquels tu as coupé les segments, en utilisant le bord de ta zone de clipping. Tu as 2 manières de relier les points de ton polygône:
1.
+---------------------+
|                     [7]|[/7]
|                     [7]|[/7]
|                     [7]|[/7]
|                     [7]|[/7]
|                     [7]|[/7]
|                     [7]|[/7]
+---------------------+

2.
                      +------------+
                      [7]|[/7]            |
                      [7]|[/7]            |
                      [7]|[/7]            |
                      [7]|[/7]            |
                      [7]|[/7]            |
                      [7]|[/7]            |
                      +------------+

Il s'agit donc de savoir laquelle est la bonne.
Pour cela, teste pour quel des 2 cas de figure la partie en noir se trouve entièrement à l'intérieur de ton polygône. Ici, tu verras que c'est le cas 2 (cf. ton dessin, c'est coupé dans mes schémas). Donc tu choisis la 2.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

4

Ca me semble raisonnable, et simple en plus, expliqué comme ça grin
merci Kevin top

5

heuuuu c koi du clipping?? ca sert a quoi??
Casio a quand meme un certains merite:
ils ont inventé les calculatrices jettables :D.

6

À éviter d'écrire en dehors de l'écran.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

7

Ca paraissait simple, mais en fait prouver qu'un point est à l'interieur d'un polygone est assez compliqué...
J'essais à partir du pseudo-code de cette page...mad
Y a t'il une fonction existante qui prouve qu'un point est dans un polygone? (j'en ai marre de reinventer la roue)

8

Tu décompose le polygone en triangles et tu vérifie pour chaque triangle si le point en fait partie. ça peut peut-être marcher, non ?
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

9

ben je pense que la methode serait la même au final, c'est a dire tester la demie-droite qui part du point et tester le nb d'intersections avec le triangle. (à moins qu'il existe une technique pour tester un point et un triangle?)

Le probleme c'est de gerer toutes les exceptions, comme lorsque la demie droite est coplanaire avec un des segments du polygone, ou si la demie droite passe par un point du polygone.(cf lien en #6)

10

Sinon, tu définis l'ordre des sommets de ton poly d'une façon bien précise qui te permet de faciliter le test d'inclusion.
Je réfléchis et si je trouve un truc bien je le poste (si je ne me suis pas endormi entre-temps parce que je suis crevé)
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

11

Mmh c'est bon, j'ai trouvé une technique.
Par contre, elle est compliquée à expliquer et lente sûrement.
Donc, ton polygone dans lequel tu veux tester l'inclusion d'un point, tu le définis de façon à ce que tous les points de suivent (ah, j'oubliais, ça ne marche qu'avec les poly convexes). Ensuite, tu prends ton point et tu fais un produit vectoriel entre le vecteur qui a pour origine le point et pour extrémité le sommet n°1 (par exemple) et le vecteur qui a pour origine le sommet 1 et pour extrémité le sommet 2. Ça te donne une valeur. Positive ou négative, selon la position du point par rapport à la droite formée par les sommets 1 et 2. Tu fais ça pour chaque côté du polygone et à la fin, si tous tes produits vectoriels étaient du même signe, c'est que le point est à l'intérieur, sinon, il est à l'extérieur smile
J'espère que je ne raconte pas n'importe quoi.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

12

Ah oui, et dans le cas où ton point est en intersection avec un des côtés, ça devrait donner un produit vectoriel nul, si je ne me trompe pas.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

13

En fait, dans ce cas, si le point(coin de l'ecran) est en intersection avec un coté(du polygone) je peux le deduire par avance en comparant la liste des points du polygone avec les points de l'ecran. mais merci quand même.

Sinon j'ai eu une idée, je vais essayer de l'appliquer, qui prend en compte le sens du polygone.
Si le polygone coupe l'écran horizontalement en 2points A et B, et que dans la liste des points du polygone, A est avant B, alors je rempli à gauche, et inversement.(ou plutot j'ajoute les 2 sommets de l'ecran à mon polygone)
mais bon, je ne sais pas encore si ça va marcher...

14

Hmmm, ça pourrait marcher si tu mets toujours les points dans le même sens (toujours direct ou toujours indirect).

Sinon, ce que tu peux faire est travailler avec des voisinages plutôt qu'avec les segments entiers. (Bon, je m'excuse auprès des experts de Mathématiques si j'utilise mal le terme de voisinage, je sais que je l'utilise mal, mais je veux expliquer le problème sans présupposer un niveau élevé en Mathématiques.) Tu as tes 2 points d'intersection, et tu étudies les voisinages de ces points d'intersection:
 [7]+-[/7]
 [7]|[/7]
 [7]|[/7]
[12]-[/12]+[4]-[/4]
 [7]|[/7]
 [7]|[/7]
 [7]|[/7]
 [7]|[/7]
 [7]|[/7]
[12]-[/12]+[4]-[/4]
 [7]|[/7]
 [7]|[/7]
 [7]+-[/7]

Tu as le voisinage bleu et le voisinage rouge. Il s'agit à savoir lequel est dans ton polygône. (Il y en a forcément un à l'intérieur et un à l'extérieur.) Mais je ne sais pas si ça apporte vraiment quelque chose.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

15

Tu clippes ton polygone par rapport a chaque droite qui forme l'ecran, et tu stockes le resultat (c'est ce qu'ils font en 3D) dans une variable temp. A la fin, tu as ce qu'il faut smile

Sinon tu utilises l'algo de Fast Clipping 2D de chaisplusqui. Pas mal, mais assez complexe a mettre ne oeuvre.

16

heu oue, fais comme PpHd a dit... tu prends chaque cote de ton ecran et tu decoupe ton poly avec. pour le cote suivant, tu decoupe le nouveau poly genere, ainsi dessuite...
a chaque decoupage, tu te retrouve avec au maximum deux nouveaux points pour un poly convexe...
In many respects the Yoshi is like a beautiful woman. A man can come so enamoured that he bestows on her all his time, his energy and his fortune.
- Fred whipple, 1960

*** Ne sous-estimez pas la puissance de la Marmotte ***
© Marmotte Team : LaMarmotte, sBibi, Vark & Sabrina

17

Oui, mais le problème c'est pas le clipping (qui marche bien) mais le remplissage.

Pour info, j'ai reussi smile en utilisant l'algorithme de Weiler-Atherton:
(Valable pour polygones et clôtures concaves et avec trous.)
Ordonner les sommets du polygone et de ses éventuels trous dans le même sens, et ordonner dans le sens opposé la clôture et ses trous.
Calculer tous les points d'intersection des côtés du polygone avec tous ceux de la clôture, les insérer dans la liste des sommets du polygone et de la clôture.
Relier le même point d'intersection, présent dans les deux listes, polygone et clôture, par des liens bi-directionels.

Partir d'un point du polygone intérieur à la clôture, suivre la liste en copiant les sommets dans le polygone résultat, jusqu'à arriver à un point d'intersection. Utiliser le lien pour passer au même point dans la liste de la clôture. Copier les sommets de la liste de la clôture jusqu'à un point d'intersection, et changer à nouveau de liste en utilisant le lien.

18

Oui, mais le problème c'est pas le clipping (qui marche bien) mais le remplissage.


nan nan, ce dont je parle, quand ca te clip ca te sort un polygone clippe, pas des lignes clippees grin
(polygone clippe, donc forme convexe fermee grin)

bon, en pseudo code, ca donne un truc comme ca, et ca m'a l'air bcp plus adapte que la methode que t'utilise qui a l'air bcp plus general mais aussi bcp plus lourde:

void clip_poly_to_plane(poly *pin, poly *pout, plane *p)
{
float firstdot;
float curdot;
float nextdot;
int curin;
int nextin;
vertex *curvert;
vertex *nextvert;
vertex *outvert;

outvert = pout->verts;
nextvert = curvert = pin->verts;
firstdot = curdot = dot(curvert->coord, p->normal);
while (--pin->nvertices)
 {
  nextvert++;
  nextdot = dot(nextvert->coord, p->normal);
  nextin = (nextdot >= p->dist) ? 1 : 0;
  if (curin) // si le point est devant le plan
   {
    *outvert = *curvert; // on garde ce vertex dans le poly clippe
    outvert++;
    pout->nvertices++;
   }
if (curin != nextin) // si le point n'ext pas du meme cote que le precedent, on clippe et on insere le vertex clippe
 {
  float scale;

  // clip
  scale = (p->dist - curdot) / (nextdot - curdot);
  outvert->x = curvert->x + (nextvert->x - curvert->x) * scale;
  outvert->y = curvert->y + (nextvert->y - curvert->y) * scale;
  outvert->y = curvert->z + (nextvert->z - curvert->z) * scale;
  outvert++;
  pout->numvertices++;
 }
  // sinon, les deux sont dehors et on insere kedal

  curdot = nextdot;
  curvert++;
  curin = nextin;
 }

// arrive ici, on doit tester le lien entre le dernier et le premier point (pour boucler le poly)

nextvert = pin->verts;
nextdot = firstdot;
nextin = (nextdot >= p->dist) ? 1 : 0;
if (curin) // si le point est devant le plan
 {
  *outvert = *curvert; // on garde ce vertex dans le poly clippe
  outvert++;
  pout->nvertices++;
 }
if (curin != nextin) // si le point n'ext pas du meme cote que le precedent, on clippe et on insere le vertex clippe
 {
  float scale;

  // clip
  scale = (p->dist - curdot) / (nextdot - curdot);
  outvert->x = curvert->x + (nextvert->x - curvert->x) * scale;
  outvert->y = curvert->y + (nextvert->y - curvert->y) * scale;
  outvert->y = curvert->z + (nextvert->z - curvert->z) * scale;
  outvert++;
  pout->numvertices++;
 }
}



et t'appelle cette fonction pour chaque plan de l'ecran, en passant a chaque fois le poly que le precedent appel a renvoye.
bon heu j'ai tape ca a la volee, ca marche surement pas tel quel, c'est juste pour l'algo general smile

et tu peux clipper n'importe quoi, pas que les coordonnees des vertices du poly, mais tout ce qui devra/pourra etre interpole: les couleurs, coords de textures, normales, etc...
In many respects the Yoshi is like a beautiful woman. A man can come so enamoured that he bestows on her all his time, his energy and his fortune.
- Fred whipple, 1960

*** Ne sous-estimez pas la puissance de la Marmotte ***
© Marmotte Team : LaMarmotte, sBibi, Vark & Sabrina

19

heu bon, hormis 2-3 erreurs de copier coller que g la flemme de corriger, ca devrait a peu pres marcher smile
(ah oui, avec ca tu peux clipper contre ta piramyde de vision, donc en 3D, pas que en 2D... si tu le passe en 2D pure, ca devrait encore plus simplifier les calculs, sachant que les plans sont soit completement horizontaux, soit completement verticaux. tu peux meme derouler la boucle et inserer du code specifique a chaque cote, si ils sont pas ammenes a changer. tu peux aussi rendre la fct plus petite en indexant les vertices du polygone d'entree au lieu d'incrementer un pointeur vers le buffer de vertices, et indexer avec [index % pin->nvertices], comme ca tu retombe directement sur le premier point quand t'es au dernier tour de boucle, mais ca te fait calculer plus de trucs (2 * le meme produit scalaire))

et pour l'appeller, un truc du genre:

void ...(.., poly *pin)
{
poly pout;

clip_poly_to_plane(pin, &pout, &(frustrum->plane[LEFT]));
if (pout.numverts < 3)
return;
clip_poly_to_plane(&pout, pin, &(frustrum->plane[RIGHT]));
if (pin->numverts < 3)
return;
clip_poly_to_plane(pin, &pout, &(frustrum->plane[TOP]));
if (pout.numverts < 3)
return;
clip_poly_to_plane(&pout, pin, &(frustrum->plane[BOTTOM]));
}

In many respects the Yoshi is like a beautiful woman. A man can come so enamoured that he bestows on her all his time, his energy and his fortune.
- Fred whipple, 1960

*** Ne sous-estimez pas la puissance de la Marmotte ***
© Marmotte Team : LaMarmotte, sBibi, Vark & Sabrina

20

je te remercie, j'etudie ça et je le testerais surement, vus que j'avais encore quelques rares bugs d'affichage. (cas ou les polygonnes etaient decris dans le sens inverse je crois (ce qui ne devrait pas arriver en 3D?non?) )
thx smile

21

Pour Ti je te deconseille d'utiliser les floats. Pour GP aussi.

22

PpHd> bah dans son cas, il fait ca en javascript donc bon, je pense pas que ca change qquechose trigni
In many respects the Yoshi is like a beautiful woman. A man can come so enamoured that he bestows on her all his time, his energy and his fortune.
- Fred whipple, 1960

*** Ne sous-estimez pas la puissance de la Marmotte ***
© Marmotte Team : LaMarmotte, sBibi, Vark & Sabrina