===== TD2 Remplissage ===== ==== Tracer un disque ==== On supposera disposer d'une fonction ''SegHori(x1, x2, y)'' trançant un segment horizontal. Ecrire un algorithmes qui n'utilise que des opérations sur les entiers pour tracer un disque (constitué de pixels à l'intérieur d'un cercle). Stratégie : rajouter des appels à ''SegHori'' dans [[fain_cercles#algorithme_de_bresenham|l'algo de tracer de cercle de Bresenham]]. disque (rayon R, couleur C) x=0; y=R; d=3-2*R; // initialisation tant que (x =< y) faire SegHori(-x, x, y, C); // octants II et III SegHori(-x, x, -y, C); // octants VI et VII SegHori(-y, -x, x, C); // octant IV SegHori( x, y, x, C); // octant I SegHori(-y, -x, -x, C); // octant V SegHori( x, y, -x, C); // octant VIII si ( d>0 ) {d=d+4*x+6;} sinon {d=d + 4*(x-y) + 10; y=y-1; } x=x+1; ==== Remplir un Polygône par Balayage ==== Soit un polygône quelconque, qui peut n'être ni régulier, ni convexe, ni simple. === Structures de données === Pour le sommet, l'arête et le polygone : comment organiser le stockage des données? * sommet : un point? ou un point et la liste des arêtes incidents? //juste un point// * arêtes : deux extrémités donc deux points? //oui, c'est ça // * polygone : liste chainée des arêtes? // oui, plus le nombre d'arêtes. // Le corrigé propose typedef struct point_t { int x,y; } point_t; typedef struct arete_t { point_t p1, p2; } arete_t; typedef struct polygone_t { int nb_aretes; arete_t *arete; } polygone_t; === Les Coupes === La demi-droite horizontale y=Y0 coupe le polygone en n points x_j. Comment stocker ces intersections? Comment s'en servir pour colorier les points de la droite horizontale qui appartiennent à l'intérieur du polygone? En fait, ce sera la liste des pixels (point_t) appartenant aux arêtes, triés (ordre croissant) par y et puis par x. Pour un y donné, la liste fournira les points d'instersection successifs. == corrigé == Le corrigé propose une liste chainée mais des seuls xj. Voyons où ça nous menera. typedef struct Xintersection_t { int xj; struct Xintersection_t *next; } Xintersection_x_t; Ensuite, on va supposer qu'il n'y a pas d'intersections avec des sommets : comment serait-ce possible? Mais on traitera cette question plus tard. - Trier les intersections par ordre croissant - InterA = tête de liste; - InterB = InterA->next; - Répéter jusqu' la fin de la liste (==InterB) - SegHori(InterA, InterB, y); - InterA=InterB->next; - InterB=InterA->next; ==== Calcul des autres points d'intersection ==== Plusieurs méthodes sont proposées dans le corrigé, dont deux avec des calculs flottants. Passons tout de suite à l'algorithme entier. Le but est de calculer les xj pour y+1; on se limite à l'ensemble des arêtes actives...on verra plus tard comment gérer les entrées en, et sorties d'activité. typedef struct arete_active_t { int xj; int DyFoisDistCD; int DX, Dy; struct arete_active_t *next; } arete_active_t; Le principe est d'utiliser la connaissance de la pente de l'arête pour calculer l'incrément en x lorsque y augment par 1. - y = quelque chose - Tant que y n'a pas été augmenté - trier les arêtes actives par xj croissant - AA = PremièreAreteActive - BB = AA.next - Repeter jusqu'à epuisement des arêtes actives : - SegHori (AA.xj, BB.xj, y); - AA = BB.next - BB = AA.next - pour toutes les aretes actives (AA) : - AA.DyFoisDistCD = AA.DyFoisDistCD + AA.Dx - Tant que AA.DyFoisDistCD >= AA.Dy / 2 - AA.xj = AA.xj + 1 - AA.DyFoisDistCD = AA.DyFoisDistCD - AA.Dy - Tant que AA.DyFoisDistCD < - AA.Dy / 2 - AA.xj = AA.xj - 1 - AA.DyFoisDistCD = AA.DyFoisDistCD + AA.Dy - AA = AA.next - y = y+1 (fin de boucle, goto 2) ==== Remplissage du tout ==== On rajoute deux types de structures pour gérer les ensembles d'arêtes actives et inactives typedef struct arete_t { point_t inf, sup; struct arete_t *next; } arete_t; typedef struct arete_active_t { int xj; int ymax; int DyFoisDistCD; int DX, Dy; struct arete_active_t *next; } arete_active_t; - ET = liste triée des arêtes (d type arete_t) n__non__-horizontales de P dans l'ordre croissant de inf.y. - AET = liste vide (initialement) d'arêtes actives. - y = PremiereArete(ET).inf.y : la plus faible valeur de y qui peut avoir une intersection avec un arete (un sommet en l'occurrence, non?). - Tant qu'on n'a pas fini - FIXME à completer plus tard. ==== Navigation ==== [[fain_td1| ]] -- [[fain_td3|]]