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

Windows Presentation Foundation Discussion :

Ligne/courbe avec symboles répartis le long


Sujet :

Windows Presentation Foundation

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Septembre 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2013
    Messages : 14
    Points : 10
    Points
    10
    Par défaut Ligne/courbe avec symboles répartis le long
    Bonjour à tous !

    Habituellement j'arrive toujours à trouver une solution à mes problèmes mais dans le cas présent je sèche vraiment ! Voilà, je souhaite dessiner une courbe (ou ligne) sur laquelle il y aurait des flèches comme dans l'exemple ci-dessous :

    Nom : Line_Arrows.JPG
Affichages : 591
Taille : 8,6 Ko

    Je ne sais absolument pas comment m'y prendre... Au départ j'avais pensé qu'il était possible de personnaliser la forme des pointillés d'une courbe/ligne mais apparemment, à part des tirets ou des ronds, il n'y a pas de réponse de ce coté-là... Faut-il utiliser un chemin sur lequel je répéterai la forme choisie ? Y'a-t-il une solution tellement simple que je ne la vois pas ???

    Si vous avez des pistes je suis preneur !

    Merci !

    Eyerobot

  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
    c'est tellement general en termes de formulation(type de courbe :genere par primitive -fonction math -interpolee -etc ...) que ton probleme a peu de chance de recevoir de reponses...
    De toutes facons il n' y a aucune fonction dans l'api publique wpf qui dessine des symboles de ce genre -fleche-diamond personnalise- et le positionner...
    Il faut ecrire soit meme le code et le "plus simple" des container qui s'y prete est Canvas.......
    Une fleche etant simplement un triangle (curve polyline fermee ou non ferme)...
    S'il est facile facile de positionner un triangle sur une ligne verticale ou horizontale dans un canvas ...et de faire un render.transform avec un rotatetransform....
    Les choses deviennent serieusement compliquees quand il s'agit d'une courbe bezier ou autre spline car il faut connaitre Aka la droite Tangente de ta Courbe au Point de postionnemet .
    Ce qui n'est pas trivial car la courbe doit etre analytique (generee par une fonction mathematique) ou un spline(courbe qui interpole une serie de points)...
    Les 2 exemples qui suivent illustrent l'approche "custom shape " positionnee automatiquement à une fraction de la longueur de la courbe de bezier grace à la methode API qui fournit le Point et TangentePoint qui est un vecteur tangente(direction):
    -PathGeometry.GetPointAtFractionLength(progress, out point, out tangentepoint);
    Exemple 1 :
    -utilise un custom shape CurveSymbol
    -utilise la methode GetPointAtFractionLength pour dessiner un Circle positionne à la 2eme et 3e fraction de chacun des 2 BezierSegments inclus dans le PolyBezierSegment(peut en avoir plus)...sans s'occuper de l'orientation puisque c'est un cercle...
    code behind.cs du custom shapeCurveSymbol:
    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Shapes;
    using System.Windows.Media;
    using System.Windows;
     
    namespace WpfSplineArrow
    {
             public class CurveSymbol : Shape
            {
                private PathGeometry pathgeo;
                private PathFigure figureBezier;
                private PolyBezierSegment polysegBezier;
     
     
     
                List<EllipseGeometry> circleFigures;
                public CurveSymbol()
                {
     
                    Stroke = Brushes.Blue;
                    StrokeThickness = 2.0;
     
     
     
     
                }
                protected override Geometry DefiningGeometry
                {
                    get { return CurveGeometry(); }
                }
     
     
                private Geometry CurveGeometry()
                {
                    polysegBezier = new PolyBezierSegment();
                    figureBezier = new PathFigure();
                    figureBezier.IsClosed = false;
                    figureBezier.IsFilled = false;
                    figureBezier.Segments.Add(polysegBezier);
                    pathgeo = new PathGeometry();
                    pathgeo.Figures.Add(figureBezier);
     
     
                    circleFigures = new List<EllipseGeometry>();
     
     
                    polysegBezier.Points = DataPoints;
     
     
                    int division = polysegBezier.Points.Count;
     
                    for (int i = 0; i < division ; i++)
                    {
     
                        EllipseGeometry ellip = new EllipseGeometry();
                        circleFigures.Add(ellip);
     
                    }
     
                    double fraction = 1.0 / (double)division;
                    double progress = 0;
     
     
                    for (int i = 1; i < division-1; i++)
                    {
                        Point p1;
                        Point p;
                        progress = fraction*(double)i;
     
                        pathgeo.GetPointAtFractionLength(progress, out p1, out p);
     
     
     
                        //if (progress == 1.0 || progress > 1.0) break;
     
                        pathgeo.AddGeometry(CalculateCircle(circleFigures[i], p1));
                    }
     
     
     
                    return pathgeo;
     
                }
     
                EllipseGeometry CalculateCircle(EllipseGeometry ellip, Point pt1)
                {
                    ellip.Center=pt1;
                    ellip.RadiusX = RadiusX ;
                    ellip.RadiusY = RadiusY;
     
                    return ellip;
                }
     
                public PointCollection DataPoints
                {
                    get { return (PointCollection)GetValue(DataPointsProperty); }
                    set { SetValue(DataPointsProperty, value); }
                }
     
                // Using a DependencyProperty as the backing store for DataPoints.  This enables animation, styling, binding, etc...
                public static readonly DependencyProperty DataPointsProperty =
                    DependencyProperty.Register("DataPoints",
                    typeof(PointCollection), typeof(CurveSymbol),
                    new FrameworkPropertyMetadata(new PointCollection()));
     
     
     
     
                public double  RadiusX
                {
                    get { return (double )GetValue(RadiusXProperty); }
                    set { SetValue(RadiusXProperty, value); }
                }
     
                // Using a DependencyProperty as the backing store for RadiusX.  This enables animation, styling, binding, etc...
                public static readonly DependencyProperty RadiusXProperty =
                    DependencyProperty.Register("RadiusX", 
                    typeof(double ),
                    typeof(CurveSymbol), 
                    new FrameworkPropertyMetadata(10.0,
                    FrameworkPropertyMetadataOptions.AffectsMeasure ));
     
     
     
                public double  RadiusY
                {
                    get { return (double )GetValue(RadiusYProperty); }
                    set { SetValue(RadiusYProperty, value); }
                }
     
                // Using a DependencyProperty as the backing store for RadiusY.  This enables animation, styling, binding, etc...
                public static readonly DependencyProperty RadiusYProperty =
                    DependencyProperty.Register("RadiusY", typeof(double ),
                    typeof(CurveSymbol ),
                    new FrameworkPropertyMetadata(10.0,
                    FrameworkPropertyMetadataOptions.AffectsMeasure));
     
     
     
     
     
            }
        }
    code xaml du form utilisateur:
    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
     
    <Window x:Class="WpfSplineArrow.Window2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfSplineArrow" 
            Title="Window2" Height="350" Width="525">
        <Grid>
             <!--<local:CurveSymbol
                Fill="Yellow" 
                RadiusX="15"
                RadiusY="15"
                DataPoints= "10,10 200,0 300,100 300,0 400,0 600,100" >
     
     
            </local:CurveSymbol>-->
        </Grid>
    </Window>
    Exemple 2 plus corse :
    -utilise un custom shape MyCurve dont la Longueur ,l'angle d'ouverture et IsClosed(fleche triangle ou ouverte) peuvent etre specifies...
    -utilise la methode GetPointAtFractionLength pour dessiner un Circle positionne à la 2eme et 3e fraction de chacun des 2 BezierSegments inclus dans le PolyBezierSegment(peut en avoir plus)...
    Et se targue de dessiner une fleche en s'assurant qu'elle est oriente suivant la tangente fourni par GetPointAtFractionLength ....
    La fleche est dessine aux 2eme et 3eme fractions de chaque BezierSegment comme dans l'exemple 1 grace à la methode CalculateArrow du custom shape MyCurve...

    code behind.cs du custom shape MyCurve :
    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Media;
    using System.Windows;
    using System.Windows.Shapes;
     
    namespace WpfSplineArrow
    {
     
     
     
            public class MyCurve : Shape
            {
                private PathGeometry pathgeo;
                private PathFigure figureBezier;
                private PolyBezierSegment polysegBezier;
     
     
     
                List<PathFigure> arrowFigures;
                public MyCurve()
                {
     
                    Stroke = Brushes.Blue;
                    StrokeThickness = 2.0;
     
     
     
     
                }
                protected override Geometry DefiningGeometry
                {
                    get { return CurveGeometry(); }
                }
     
     
                private Geometry CurveGeometry()
                {
                    polysegBezier = new PolyBezierSegment();
                    figureBezier = new PathFigure();
                    figureBezier.IsClosed = false;
                    figureBezier.IsFilled = false;
                    figureBezier.Segments.Add(polysegBezier);
                    pathgeo = new PathGeometry();
                    pathgeo.Figures.Add(figureBezier);
     
     
                    arrowFigures = new List<PathFigure>();
     
     
                    polysegBezier.Points = DataPoints;
     
     
                    int division = polysegBezier.Points.Count;
     
                    for (int i = 0; i < division ; i++)
                    {
     
                        PathFigure    arrowFig = new PathFigure();
                        PolyLineSegment segLine = new PolyLineSegment();
                        arrowFig.Segments.Add(segLine);
                        arrowFigures.Add(arrowFig);
     
                    }
     
                    double fraction = 1.0 / (double)division;
                    double progress = 0;
     
     
                    for (int i = 1; i < division-1; i++)
                    {
                        Point p1;
                        Point p;
                        progress = fraction*(double)i;
     
                        pathgeo.GetPointAtFractionLength(progress, out p1, out p);
     
                        Vector v = (Vector)p;
                        Point p2 = Point.Add(p1, v);
     
                        if (progress == 1.0 || progress > 1.0) break;
     
                        pathgeo.Figures.Add(CalculateArrow(arrowFigures[i], p1, p2));
                    }
     
     
     
                    return pathgeo;
     
                }
     
                PathFigure CalculateArrow(PathFigure pathfig, Point pt1, Point pt2)
                {
                    Matrix matx = new Matrix();
                    Vector vect = pt1 - pt2;
                    vect.Normalize();
                    vect *= ArrowLength;
     
                    PolyLineSegment polyseg = pathfig.Segments[0] as PolyLineSegment;
                    polyseg.Points.Clear();
                    matx.Rotate(ArrowAngle / 2);
                    pathfig.StartPoint = pt2 + vect * matx;
                    polyseg.Points.Add(pt2);
     
                    matx.Rotate(-ArrowAngle);
                    polyseg.Points.Add(pt2 + vect * matx);
                    pathfig.IsClosed = IsArrowClosed;
     
                    return pathfig;
                }
     
                public PointCollection DataPoints
                {
                    get { return (PointCollection)GetValue(DataPointsProperty); }
                    set { SetValue(DataPointsProperty, value); }
                }
     
                // Using a DependencyProperty as the backing store for DataPoints.  This enables animation, styling, binding, etc...
                public static readonly DependencyProperty DataPointsProperty =
                    DependencyProperty.Register("DataPoints",
                    typeof(PointCollection), typeof(MyCurve),
                    new FrameworkPropertyMetadata(new PointCollection()));
     
     
     
                /// <summary>
                ///     Identifies the IsArrowClosed dependency property.
                /// </summary>
                public static readonly DependencyProperty IsArrowClosedProperty =
                    DependencyProperty.Register("IsArrowClosed",
                        typeof(bool), typeof(MyCurve),
                        new FrameworkPropertyMetadata(false,
                                FrameworkPropertyMetadataOptions.AffectsMeasure));
     
                /// <summary>
                ///     Gets or sets the property that determines if the arrow head
                ///     is closed to resemble a triangle.
                /// </summary>
                public bool IsArrowClosed
                {
                    set { SetValue(IsArrowClosedProperty, value); }
                    get { return (bool)GetValue(IsArrowClosedProperty); }
                }
                /// <summary>
                ///     Identifies the ArrowAngle dependency property.
                /// </summary>
                public static readonly DependencyProperty ArrowAngleProperty =
                    DependencyProperty.Register("ArrowAngle",
                        typeof(double), typeof(MyCurve),
                        new FrameworkPropertyMetadata(45.0,
                                FrameworkPropertyMetadataOptions.AffectsMeasure));
     
                /// <summary>
                ///     Gets or sets the angle between the two sides of the arrowhead.
                /// </summary>
                public double ArrowAngle
                {
                    set { SetValue(ArrowAngleProperty, value); }
                    get { return (double)GetValue(ArrowAngleProperty); }
                }
     
                /// <summary>
                ///     Identifies the ArrowLength dependency property.
                /// </summary>
                public static readonly DependencyProperty ArrowLengthProperty =
                    DependencyProperty.Register("ArrowLength",
                        typeof(double), typeof(MyCurve),
                        new FrameworkPropertyMetadata(12.0,
                                FrameworkPropertyMetadataOptions.AffectsMeasure));
     
                /// <summary>
                ///     Gets or sets the length of the two sides of the arrowhead.
                /// </summary>
                public double ArrowLength
                {
                    set { SetValue(ArrowLengthProperty, value); }
                    get { return (double)GetValue(ArrowLengthProperty); }
                }
     
     
            }
        }
    code xaml du form utilisateur:
    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
     
    <Window x:Class="WpfSplineArrow.Window2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfSplineArrow" 
            Title="Window2" Height="350" Width="525">
        <Grid>
            <local:MyCurve
                Fill="Yellow" 
                ArrowAngle="45"
                ArrowLength="25"
                IsArrowClosed="True" 
                DataPoints= "0,0 200,0 300,100 300,0 400,0 600,100" >
     
     
            </local:MyCurve>
           </Grid>
    </Window>
    bon code...

Discussions similaires

  1. Réponses: 3
    Dernier message: 06/03/2014, 20h19
  2. compteur de ligne excel avec filtre
    Par calimero91 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 14/12/2005, 11h04
  3. retour ligne intélligent avec l'utilisation de DIV
    Par bébé dans le forum Balisage (X)HTML et validation W3C
    Réponses: 8
    Dernier message: 22/08/2005, 17h46
  4. lignes 3d avec d3dx
    Par izbad dans le forum DirectX
    Réponses: 12
    Dernier message: 21/04/2005, 15h31
  5. Génération de lignes entières avec TEXT_IO.PUT
    Par ludo.guy dans le forum Oracle
    Réponses: 9
    Dernier message: 13/10/2004, 15h28

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