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

C# Discussion :

Graphics.DrawPolygon et Pen.Alignement = Inset = Problème ?


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 31
    Points
    31
    Par défaut Graphics.DrawPolygon et Pen.Alignement = Inset = Problème ?
    Bonjour,

    Je viens poster aujourd'hui car j'ai un problème dans les conditions suivantes :

    - J'ai un polygone à dessiner (DrawPolygon)
    - Mon Pen utilisé est en Alignement = Inset
    - Mon Pen a une largeur de tracé d'au moins 2

    Le résultat que j'obtiens est assez surprenant, certaines "parties" de mon polygone se retrouvent remplies, comme avec un Fill.
    De plus, ces parties varient en fonction de l'épaisseur du Pen (et une partie "remplie" à Width 2 peut en pas l'être à Width 3 par exemple)
    Je n'arrive d'ailleurs même pas à identifier exactement ce qui différencie les zones qui se remplissent des autres, même si il semble y avoir un lien avec le fait qu'elle soit quasiment fermée.

    Si quelqu'un a une idée autre que de garder une épaisseur de tracé de 1 ou repasser l'alignement en Center, ça m’intéresserait beaucoup

    Voilà en image le résultat que j'obtient (avec un simple DrawPolygon sans Fill soyons d'accord).

    Nom : Sans titre 1.png
Affichages : 232
Taille : 31,7 Ko

    Je vous mets en pièce jointe le projet de test, avec un fichier contenant les points que j'utilise et qui me génère ces remplissages.

    Merci d'avance !
    Fichiers attachés Fichiers attachés

  2. #2
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut
    bonjour

    La MSDN Help signale que la valeur Inset de PenAlignement peut avoir "un comportement aleatoire"(texto) et je je suggere donc d'abandonner cette voie...

    Une autre issue plus practicable c'est d'utiliser le "decalage" ou outline d'un trace grace à la function Widen() du class GraphicsPath...
    Cette function a pour effet de tracer une figure (rectangle,ellipse et autres courbes) avec 2 contours englobants par rapport à la ligne du trace en cours d'une largeur de décalage spécifiée par le "width" d'un Pen transmis en parametre...
    Le pen Widen ne sert pas à tracer necessairement mais juste à specifier le decalage et un autre Pen peut etre utilse avec un width souhaite graphiquement comme dans ce bout de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
            Pen penw = new Pen(Color.Transparent, 20.0f);
            Rectangle r = new Rectangle(50, 50, 300, 150);
     
            path.AddRectangle(r);
            pth.Widen(penw);
            gr.DrawPath(Pens.Blue, pth);
    code behind .cs d'un form avec un exemple complet :

    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing.Drawing2D;
     
    namespace TestPenInset
    {
        public partial class FormWidenPath : Form
        {
     
     
            public FormWidenPath()
            {
                InitializeComponent();
            }
     
            private void FormWidenPath_Paint(object sender, PaintEventArgs e)
            {
                Graphics gr = e.Graphics;
     
                Rectangle r= new Rectangle(50, 50, 300, 150);//rectangle
                List<PointF> pts  = GetPoints(); //polygone
     
     
                using (GraphicsPath path =new GraphicsPath())
                {
                         using (Pen penRed = new Pen(Color.Red, 1.0f))
                        {
     
                            //rectangle ligne theorique
                            r = new Rectangle(50, 50, 300, 150);
                            path.AddRectangle(r);
                            gr.DrawPath(penRed, path); 
     
                            //polygon ligne theorique
                            path.Reset();
                            path.AddPolygon(pts.ToArray());
                            gr.DrawPath(penRed, path);
                         }
     
                         using (Pen penWiden = new Pen(Color.Transparent, 20.0f))
                         {
                             using (Pen penBlue = new Pen(Color.Blue, 1.0f))
                             {
     
                                 //rectangle avec decalage de 20.0f
                                 path.Reset();
     
                                 path.AddRectangle(r);
                                 path.Widen(penWiden);
     
                                 gr.DrawPath(penBlue, path);
                                 using (SolidBrush fill = new SolidBrush(Color.FromArgb(100, Color.Tomato)))
                                 {
                                     gr.FillPath(fill, path);
                                 }
     
     
     
                                 //polygon   avec decalage de 20.0f
     
                                 path.Reset();
     
                                 path.AddPolygon(pts.ToArray());
                                 path.Widen(penWiden);
     
                                 gr.DrawPath(penBlue, path);
                                 using (SolidBrush fill = new SolidBrush(Color.FromArgb(100, Color.Tomato)))
                                 {
                                     gr.FillPath(fill, path);
                                 }
     
                             }
                         }
     
                }
     
     
            }
            //pentagone (figure à 5 cotes)
            private List<PointF> GetPoints()
            {
     
                float radius = 100.0f;
                PointF center = new PointF(400, 400);
                double theta = 2*Math.PI / 5.0;
                double angle = 0.0; 
     
                List<PointF> l = new List<PointF>();
                for (int i = 0; i < 5; i++)
                {
     
                    float x = center.X + radius * (float)Math.Cos(angle);
                    float y = center.Y + radius * (float)Math.Sin(angle); 
                    PointF p = new PointF(x, y);
                    l.Add(p);
                    angle += theta;
                }
                return l;
            }
        }
    }
    code behind .cs de ton code revu qui devrait ressembler à ceci:

    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Drawing.Drawing2D;
     
    namespace TestPenInset
    {
        public partial class Form2 : Form
        {
            private Pen _pen;
            private Point[] _points;
     
     
            // ton widen pen est variable et c'est lui qu'on incremente en  fait 
            // pour augmenter ou diminuer la largeur à souhait...!!!
     
            private Pen widenPen ; 
            private SolidBrush fill ;
            private float inc = 0.2f; //increment
            private float w = 1.0f;   // width initial du widen pen
     
            public Form2()
            {
                InitializeComponent();
                _pen = new Pen(Color.Red, 1.0f);
                _pen.Alignment = PenAlignment.Center;
     
     
                widenPen = new Pen(Color.DarkBlue , w);
                widenPen.Alignment = PenAlignment.Center;
                fill = new SolidBrush(Color.Red );
     
                LoadPoints("../../Data/Points.txt");
                PaintLabel();
                PaintImage();
            }
            private void LoadPoints(String fileName)
            {
                List<Point> listPoints = new List<Point>();
                StreamReader reader = new StreamReader(fileName);
     
                while (!reader.EndOfStream)
                {
                    String[] tab = reader.ReadLine().Split(';');
                    listPoints.Add(new Point(Int32.Parse(tab[0]), Int32.Parse(tab[1])));
                }
     
                _points = listPoints.ToArray();
     
                reader.Close();
            }
            private void PaintImage()
            {
                Bitmap bmp = new Bitmap(pictureBox.Width, pictureBox.Height);
                Graphics g = Graphics.FromImage(bmp);
                g.SmoothingMode = SmoothingMode.HighQuality;
     
     
                //vu que tu dessines sur un bitmap ,il faut translater l'origine
                // du motif d'une valeur egale au width du widenPen(epaisseur decalage)
     
                g.TranslateTransform(w,w);
     
                using (GraphicsPath path = new GraphicsPath() )
                {
                    path.AddPolygon(_points);
                    path.Widen(widenPen);
     
                    g.FillPath(fill, path);
                    g.DrawPath(_pen, path);
     
     
                }
                pictureBox.Image = bmp;
            }
            private void btnWidthMinus_Click(object sender, EventArgs e)
            {
                if (w >= 1.0f) w -= inc;
                {
                    widenPen.Width = w;
     
                    PaintImage();
                    PaintLabel();
                }
     
            }
     
            private void btnWidthPlus_Click(object sender, EventArgs e)
            {
                w += inc;
     
                widenPen.Width = w;
                PaintImage();
                PaintLabel();
            }
            private void PaintLabel()
            {
                label1.Text = widenPen.Width.ToString();
            }
            //Abend du PenAlignment
            private void rdo_CheckedChanged(object sender, EventArgs e)
            {
                //myPen.Alignment = rdoCenter.Checked ? PenAlignment.Center : PenAlignment.Inset;
                //PaintImage();
     
            }
        }
    }
    bon code....

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 31
    Points
    31
    Par défaut
    Merci pour ta réponse.

    Malheureusement, cette solution ne revient qu'à translater un tracé en Alignement Center, et non pas à tracer uniquement à l'intérieur de la forme.

    En grossissant l'épaisseur de tracé, on voit qu'il se déplace vers en bas à droite. Le but originel étant que le tracé ne puisse que "remplir" la forme sans dépasser.

  4. #4
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut
    bonjour

    Si le souci est de recuperer uniquement le "contour interieur" ,après avoir "widened" le path tu peux le recuperer à partir de Path.Points...

    il suffit d'iterer de Path.Point/2 à Path.Points.Count:

    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
     
    //polygon   avec decalage de 20.0f
     
                                 path.Reset();
     
                                 path.AddPolygon(pts.ToArray());
                                 path.Widen(penWiden);
     
     
                                 //BOUCLE  POUR RECUPERER LE "CONTOUR INTERNE"
                                 List<PointF> temp= new List<PointF>();  //Path store ses points en float...
                                 for (int i = path.PointCount/2 -2; i < path.PointCount; i++)
     
                                 {
                                     temp.Add(path.PathPoints[i]);
                                 }
                                 path.Reset();
                                 path.AddPolygon(temp.ToArray());
                                 gr.DrawPath(penBlue, path);
                                 using (SolidBrush fill = new SolidBrush(Color.FromArgb(100, Color.Tomato)))
                                 {
                                     gr.FillPath(fill, path);
                                 }
    bon code........

Discussions similaires

  1. BoxLayout alignement plusieurs problèmes.
    Par lotto90 dans le forum Agents de placement/Fenêtres
    Réponses: 2
    Dernier message: 26/07/2012, 14h33
  2. Réponses: 1
    Dernier message: 22/12/2005, 11h23
  3. [xsl:fo] problème avec external-graphic
    Par jehlg dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 11/10/2005, 11h57
  4. Problème d'alignement
    Par zorely dans le forum Mise en forme
    Réponses: 4
    Dernier message: 09/08/2005, 10h52
  5. Réponses: 13
    Dernier message: 23/12/2004, 18h01

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