IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

[Cairo] Remplissage de polygones


Sujet :

GTK+ avec C & C++

  1. #1
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut [Cairo] Remplissage de polygones
    Bonjour.

    Est-il possible de faire du remplissage de polygone avec cairo ?

    Par exemple je dessine un cube en 2D isométrique avec cairo. Puis-je utiliser une texture quelconque pour remplir les côtés de ce cube comme le ferait OpenGl par exemple ?

  2. #2
    Membre confirmé
    Profil pro
    Retraité
    Inscrit en
    Novembre 2009
    Messages
    329
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2009
    Messages : 329
    Points : 606
    Points
    606
    Par défaut
    Oui, c'est assez bien expliqué dans ce tutoriel: http://www.dil.univ-mrs.fr/~regis/CM-CAIRO/index.html
    GraceGTK: a plotting tool at https://sourceforge.net/projects/gracegtk

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Je ne suis pas sûr que j'y trouve mes petits .

    Ce que je cherche à faire c'est du mapping de texture. La texture appliquée doit se déformée pour prendre toute la surface du polygone.

    Histoire de bien illustrer mon propos je désire par rapport à l'image ci-dessous appliquée les textures A, B et C aux polygones correspondants. D'après le lien qu tu m'as donné il semblerait qu'il ne soit possible de travailler que sur des rectangles.

    Nom : textures.png
Affichages : 416
Taille : 55,0 Ko

    Suis-je dans l'erreur ?

  4. #4
    Membre confirmé
    Profil pro
    Retraité
    Inscrit en
    Novembre 2009
    Messages
    329
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2009
    Messages : 329
    Points : 606
    Points
    606
    Par défaut
    Je pense que pour arriver à tes fins, il suffit de créer la face comme une image avec la surface texturée et d'appliquer seulement ensuite les transformations qui vont positionner cette image comme tu le souhaite.
    Il y a ici un exemple d'image transformée: https://www.cairographics.org/samples/image/
    PS: en revanche, je ne suis pas sûr que tu ne soit pas obligé de programmer toi-même les transformations prenant en compte les effets de perspective.
    GraceGTK: a plotting tool at https://sourceforge.net/projects/gracegtk

  5. #5
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Heu, j'y connais rien à la 3d, mais à mon avis utiliser un framework de dessin 2d pour faire de la 3d, c'est tendre le bâton pour se faire battre. Tu vas devoir gérer différentes matrices de transformation pour chaque face, tu auras sans doute des erreurs de positionnement dû aux arrondis ou à l'alignement sur un pixel plutôt qu'un autre, et sans doute d'autres cas limite... Si tu ne veux pas te retrouver à gérer tout toi même, utilise un framework fait pour ça. Soit directement l'opengl intégré dans GTK via GtkGlArea ou peut être une API comme cogl.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Je lis pas mal de choses sur les transformées avec des matrices mais je ne trouve pas exactement ce que je veux.

    Il y a quelques temps je me suis penché sur l'interpolation bilinéaire avec quelques succès. Je crois que je vais implémenter une petite routine adossée à cairo pour réaliser la chose.

  7. #7
    Membre régulier Avatar de Persistant
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Septembre 2016
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Septembre 2016
    Messages : 50
    Points : 73
    Points
    73
    Par défaut
    Salut à tous,

    D'après mes connaissance, Cairo ne permet pas de faire des transformation en perspective.
    Nom : perspective.jpeg
Affichages : 381
Taille : 16,7 Ko

    Je rejoins liberforce en te proposant une bibliothèque. BABL qui est utilisé par Gimp avec l'outil cage :


    PS: J'avoue ne pas savoir comment l'utiliser.

  8. #8
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Hum, de ce que me dit la wikipédia, babl gère juste les espaces de couleurs. C'est gegl (qui dépende de babl) qui gère la partie rendu en OpenGL.

    Effectivement, après recherche, cairo ne peut pas gérer des projections en perspective. Cela est dû au fait que les matrices de transformation dans cairo ne peut représenter que des transformations affines. Mais deux droites initialement parallèles auxquelles on applique une transformation affine sont forcément parallèles en sortie. Cela veut dire que la transformation de perspective n'est pas affine, et ne peut être représentée par cairo.

    Donc penche toi sur cogl ou gegl... Il y en a sans doute un qui fait le job. Tu peux lire le code de l'outil de perspective de GIMP, il doit être basé sur gegl.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  9. #9
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Le nom de l'outil (cage) m'a bien aidé...
    Le code correspondant, notamment la fonction qui a l'air de faire la transformation a l'air d'être gimp_operation_cage_transform_process dans le fichier gimpoperationcagetransform.c
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  10. #10
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Merci pour toutes ces recherches.

    Même si cette bibliothèque est intéressante, surtout du fait d'éviter de réinventer la roue, je désire aussi éviter l'importation, tant que faire ce peut, de bibliothèques tierces autres que celles de Gtk+. C'est pour cette raison que j'ai écrit plus haut le fait de vouloir me pencher sur l'interpolation.

    Après une journée de travail et une bonne nuit de sommeil l'idée a germée. Plutôt que de faire de l'interpolation je me suis dit que je pouvais simplement faire une mise à l'échelle avec une transposition de pixel à pixel en y ajoutant un angle.
    Comme je n'ai besoin de dessiner que des parallélogrammes j'ai commencé à écrire quelques lignes de code spécifiques à mes besoins. C'est loin d'être fini mais voila déjà un premier résultat :

    Nom : Capture d’écran_2017-03-10_15-01-59.png
Affichages : 358
Taille : 132,7 Ko
    À gauche l'image de départ, au centre le polygone dans lequel je veux insérer cette image et à droite le résultat.

    Je vais passer à la phase optimisation et test pour les différents cas de figures qui me concernent. Je tiens aussi à préciser que la transformation tient grosso modo en 50 lignes de codes !

  11. #11
    Membre confirmé
    Profil pro
    Retraité
    Inscrit en
    Novembre 2009
    Messages
    329
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2009
    Messages : 329
    Points : 606
    Points
    606
    Par défaut
    Si je comprend bien, tu va faire de la "perspective cavalière" (https://fr.wikipedia.org/wiki/Perspe...cavali%C3%A8re) dans laquelle, au lieu de converger vers un point de fuite deux lignes parallèles le sont toujours dans le plan de représentation.
    Une solution intermédiaire pourrai être de bien représenter la face par un trapèze (et non un parallélogramme) sans rétrécir la texture avec l'éloignement. J'avoue que je ne sais pas ce que ça donne visuellement.
    GraceGTK: a plotting tool at https://sourceforge.net/projects/gracegtk

  12. #12
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par pvincent Voir le message
    Si je comprend bien, tu va faire de la "perspective cavalière" (https://fr.wikipedia.org/wiki/Perspe...cavali%C3%A8re) dans laquelle, au lieu de converger vers un point de fuite deux lignes parallèles le sont toujours dans le plan de représentation.
    Une solution intermédiaire pourrai être de bien représenter la face par un trapèze (et non un parallélogramme) sans rétrécir la texture avec l'éloignement. J'avoue que je ne sais pas ce que ça donne visuellement.
    Oui c'est dans la perspective cavalière que je travaille. D'ailleurs je tiens à conserver la forme parallélépipède. J'ai déjà écrit un ébauche d'environnement graphique en ce sens :

    Nom : Capture d’écran_2017-03-10_18-35-38.png
Affichages : 250
Taille : 211,2 Ko

  13. #13
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Je vous livre en pâture la fonction qui permet de mapper un parallélogramme. Elle a quelques contraintes mais elle répond exactement à mes besoins.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    /* Fonction de mapping d'un parallélogramme.
     *
     * Les points A, B, C, D doivent être disposés de la sorte :
     *
     *                                 B                    A        
     *                   A                                                B
     *                                            ou
     *                                 C                    D
     *                   D                                                C
     *
     * Vous pouvez aussi utiliser cette fonction pour mapper un
     * rectangle.
     *
     * Cette fonction renvoie NULL si src est NULL, si le parallélogramme
     * représente une simple ligne verticale ou si les points AD
     * ou les points BC ne sont pas alignés verticalement.
     *
     * src : GdkPixbuf original utilisé comme texture à mapper
     * A, B, C, D : sommets du parallelogramme
     *
     * Renvoie un GdkPixbuf nouvellement créé.
     */
    GdkPixbuf*
    gdk_pixbuf_perspective_new (const GdkPixbuf *src, GdkPoint A, GdkPoint B, GdkPoint C, GdkPoint D)
    {
      if (!src)
        {
          g_printerr ("Error in gdk_pixbuf_perspective_new (); !\n src must be not NULL !\n");
          return NULL;
        }
     
      if (A.x-B.x==0)
        {
          g_printerr ("Error in gdk_pixbuf_perspective_new (); !\n A and B points are vertical aligned !\n");
          return NULL;
        }
     
      if (A.x!=D.x || B.x!=C.x)
        {
          g_printerr ("Error in gdk_pixbuf_perspective_new (); !\n A and D or B and C points are not vertical aligned !\n");
          return NULL;
        }
     
      // Les points AB et CD sont inversés
      if (A.x>B.x)
        {
          GdkPoint tmp;
     
          tmp.x = A.x; tmp.y = A.y;
          A.x = B.x; A.y = B.y;
          B.x = tmp.x; B.y = tmp.y;
     
          tmp.x = C.x; tmp.y = C.y;
          C.x = D.x; C.y = D.y;
          D.x = tmp.x; D.y = tmp.y;
        }
     
      guchar *pixels = gdk_pixbuf_get_pixels (src);
      gint rowstride = gdk_pixbuf_get_rowstride (src);
      guchar channels = gdk_pixbuf_get_n_channels (src);
      gint width = gdk_pixbuf_get_width (src);
      gint height = gdk_pixbuf_get_height (src);
      gdouble scalex, scaley;
      gint x, y;
      gint targety;
      GdkPoint Orig; // Coordonnées dans l'image originale
      GdkPixbuf *TargetPixbuf;
      gint xmax, ymax;  // Limites du boundingbox 2D
      gdouble a, b; // coefficient de droite entre les points A et B
     
      // Calcul des coefficients
      a = (A.y - B.y) / (gdouble)(A.x - B.x);
      b = ((B.y*A.x) - (B.x*A.y)) / (gdouble)(A.x - B.x);
     
      // Calcul du boundingbox
      xmax = A.x;
      if (B.x>xmax) xmax = B.x;
      if (C.x>xmax) xmax = C.x;
      if (D.x>xmax) xmax = D.x;
     
      ymax = A.y;
      if (B.y>ymax) ymax = B.y;
      if (C.y>ymax) ymax = C.y;
      if (D.y>ymax) ymax = D.y;
     
      TargetPixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, xmax, ymax);
      guchar *TargetPixels = gdk_pixbuf_get_pixels (TargetPixbuf);
      gint TargetRowstride = gdk_pixbuf_get_rowstride (TargetPixbuf);
      gint TargetChannels = gdk_pixbuf_get_n_channels (TargetPixbuf);
     
      // Effacement complet du nouveau pixbuf créé
      memset(TargetPixels, 0, TargetRowstride * (D.y - A.y));
     
      Orig.x = 0; Orig.y = 0; // Coordonnées dans l'image originale
      scalex = (B.x-A.x) / (gdouble)width; // Rapport d'échelle sur l'axe des x entre l'image source et l'image cible
      scaley = (D.y - A.y) / (gdouble)height; // Rapport d'échelle sur l'axe des y entre l'image source et l'image cible
     
      // Création du pixbuf cible
      for (y=0; y<(D.y-A.y); y++)
        {
          Orig.y = (gint)(y / scaley);
     
          for (x=0; x<(B.x-A.x); x++)
    	{
    	  Orig.x = (gint)(x / scalex);
    	  targety = y + a*x + b;
     
    	  TargetPixels[(x * TargetChannels) + (targety * TargetRowstride)] = pixels [(Orig.x * channels) + (Orig.y * rowstride)];
    	  TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 1] = pixels [(Orig.x * channels) + (Orig.y * rowstride) + 1];
    	  TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 2] = pixels [(Orig.x * channels) + (Orig.y * rowstride) + 2];
    	  if (gdk_pixbuf_get_has_alpha (src))
    	    TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 3] = pixels [(Orig.x * channels) + (Orig.y * rowstride) + 3];
    	  else
    	    TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 3] = 255;
    	}
        }
     
      return TargetPixbuf;
    }

  14. #14
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Salut gerald3d,

    je pense que tu te prends beaucoup la tête. Dans ton premier diagramme, tu avais des points de fuite, indiquant une perspective, et donc cela interdisait d'utiliser cairo vu que la forme cible n'était plus un parallélogramme.

    Maintenant que tu as mieux expliqué ce que tu voulais (perspective cavalière), cairo peut tout à faire le job. Ne pars surtout pas dans de la manipulation de GdkPixbuf, ce n'est pas adapté pour cela (je le sais, je suis déjà passé par là il y a longtemps). Cairo peut parfaitement avec ses fonctions de transformation te permettre d'obtenir le résultat attendu avec peu d'effort. Ce que tu cherches à faire, c'est du "skew":

    Regarde ici, au point "7.4 penchement d'image (skew)". Tu as même le code correspondant. C'est du GTK+ 2, mais tu ne devrais pas avoir de mal à l'adapter pour GTK+ 3.
    http://www.dil.univ-mrs.fr/~regis/CM-CAIRO/

    Une fois que ta matrice de transformation est calculée, tu peux tout à fait la stocker pour la réutiliser sur les images que tu souhaites.
    De plus, cairo fait partie des dépendances de GTK+, donc pas de dépendance supplémentaire.
    Ne tombe pas dans le syndrome NIH (Not Invented Here - en français: réinventer la roue).

    N'oublie pas non plus d'utiliser les fonctions cairo_user_to_device et cairo_device_to_user qui te permettent de facilement passer d'un repère "écran" à un repère orthogonal "comme à l'école" et te permet de facilement jongler entre les espaces de coordonnées.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. remplissage de polygone hachuré
    Par flamme34 dans le forum OpenGL
    Réponses: 1
    Dernier message: 18/02/2014, 08h44
  2. remplissage et contour d'un cercle ou polygone
    Par igor24 dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 11/06/2007, 14h34
  3. Remplissage d un polygone
    Par bdurtaut dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 06/05/2007, 10h35
  4. [Algo] Point à l'intérieur d'un polygone ?
    Par kebby dans le forum C++Builder
    Réponses: 5
    Dernier message: 23/05/2003, 13h22
  5. une ligne et un polygone convexe
    Par rekam dans le forum Algorithmes et structures de données
    Réponses: 10
    Dernier message: 20/12/2002, 10h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo