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 :

Dessin de nombreux polygones


Sujet :

Windows Presentation Foundation

  1. #1
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 9
    Points
    9
    Par défaut Dessin de nombreux polygones
    Bonjour,
    Je découvre WPF et j'ai besoin de dessiner environ 30 000 polylines ou polygones représentant des communes dans un canvas. Voici mes contraintes principales :

    -Toutes peuvent être visibles en même temps, la carte est zoomable/dezoomable
    -Je dois pouvoir sélectionner chaque polyline/polygone et accèder aux informations de l'entité (le nom, le code...) associée.
    -Les formes doivent être remplissables (avec une couleur)
    -le contrôle doit être réactif

    J'ai déjà fais une première version avec un datatemplate qui représente mes entités par des polylines comme 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
     
    <DataTemplate x:Key="EntPolyLineTemplate">                                    
                <Polyline Points="{Binding Points}" Stroke="Black" StrokeThickness="1">
                    <Polyline.ToolTip>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Margin="4" Text="{Binding Id}" FontWeight="Bold"/>
                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Name}"/>
                        </StackPanel>
                    </Polyline.ToolTip>
                    <Polyline.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform ScaleY="-1"/>
                            <TranslateTransform Y="3000"/>
                        </TransformGroup>
                    </Polyline.RenderTransform>
                    <Polyline.Style>
                        <Style TargetType="Polyline">                        
                            <Setter Property="Fill" Value="Azure"/>
                            <Style.Triggers>                            
                                <EventTrigger RoutedEvent="MouseEnter" >
                                    <EventTrigger.Actions>
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ColorAnimation Storyboard.TargetProperty="Fill.Color" From="Blue" To="Azure" Duration="0:0:0.5"/>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger.Actions>                                
                                </EventTrigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Polyline.Fill" Value="Red"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Polyline.Style>
                </Polyline>
    Toujours côté XAML voici comment je m'y prend pour affecter mes entités à un canvas:
    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
     
    <WrapPanel Name="wrapPanel1" Background="Beige">        
            <ItemsControl ItemsSource="{Binding Entities}" ItemTemplateSelector="{StaticResource entityDataTemplateSelector}">
     
                <ItemsControl.Resources>                
                </ItemsControl.Resources>
     
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>             
                        <Canvas>                        
                            <Canvas.LayoutTransform>
                                <TransformGroup>                               
                                    <ScaleTransform ScaleX="{Binding ElementName=slider1, Path=Value}" ScaleY="{Binding ElementName=slider1, Path=Value}"/>
                                </TransformGroup>                            
                            </Canvas.LayoutTransform>
                        </Canvas>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
     
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="{x:Type ContentPresenter}">
                        <Setter Property="Canvas.Left" Value="{Binding X}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>        
            <Slider Minimum="0.1" Maximum="2" Height="21" Name="slider1" Width="100" />
        </WrapPanel>
    Et enfin côté code-behind:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public Window1()
            {
                InitializeComponent();
                WPFVxf vxf = new WPFVxf();
                System.Console.Out.WriteLine("Début du parsing:"+DateTime.Now.ToString());
                vxf.load("c:\\fr_dep.vxf");
                //vxf.load("c:\\fr_infracommunale.vxf");
                System.Console.Out.WriteLine("Fin du parsing:" + DateTime.Now.ToString());
                this.DataContext = new { Entities=vxf.Entities};
            }
    Bien cette version fonctionne parfaitement sauf pour ce qui est de la réactivité, il faut bien 1 ou 2s avant de pouvoir zoomer lorsque toute la carte est affichée... Il me faut donc trouver comment améliorer tout ça.
    Mes pistes :
    -Rendre asynchrone le dessin des polylines, l'idée serait que les polylines s'affichent au fur et à mesure (quitte à ce que cela se voie à l'écran); Problème: je n'ai pas trouvé où placer la propriété IsAsync...
    -D'après MSDN utiliser des Drawing plutôt que des Shapes serait plus performant; Problème: il n'y a pas d'objet représentant un polygone, je pourrais dessiner des lines mais après comment faire pour remplir la forme crée ?? et quid du test de survol à la souris..?

    Voilà j'aurais bien besoin de votre avis, merci !

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    2 210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 210
    Points : 3 015
    Points
    3 015
    Par défaut
    Salut,

    Je ne maitrise pas les géométries (savoir ce qui est le plus performant). Par contre, ton post m'a fait penser à un article que j'avais lu et qui peut peut-être t'intéresser
    http://msdn.microsoft.com/en-us/magazine/cc185721.aspx

    J'avais testé le projet, il est plutôt puissant.

  3. #3
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 9
    Points
    9
    Par défaut
    Citation Envoyé par binoo Voir le message
    Salut,

    Je ne maitrise pas les géométries (savoir ce qui est le plus performant). Par contre, ton post m'a fait penser à un article que j'avais lu et qui peut peut-être t'intéresser
    http://msdn.microsoft.com/en-us/magazine/cc185721.aspx

    J'avais testé le projet, il est plutôt puissant.
    Merci de votre réponse
    En effet ce projet ressemble beaucoup au miens, et si j'ai bien compris, comme moi il utilise un datatemplate pour afficher ses objets "MapPolygon" sous forme d'un Polygon.
    Je pense que cette méthode fonctionne bien avec quelques centaines d'objets à afficher mais pas avec mon ordre de grandeur
    Bon appétit!

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    214
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 214
    Points : 341
    Points
    341
    Par défaut
    Tu peux également jetter un oeil à cet article qui contient un projet de Canvas virtualisé...
    www.japf.fr mon blog sur WPF et .Net

  5. #5
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 9
    Points
    9
    Par défaut
    Citation Envoyé par Jérem22 Voir le message
    Tu peux également jetter un oeil à cet article qui contient un projet de Canvas virtualisé...
    Merci, l'article est intéressant, je pense que j'essayerais cette optimisation dans un second temps...
    En fait je commence avec une vue globale de la carte, ensuite l'utilisateur pourra zoomer s'il le souhaite. A ce que j'ai compris cette méthode de virtualisation (= création dynamique?) est intéressante lorsqu'on est déjà avec un zoom élevé.
    Je cherche toujours comment rendre asynchrone l'affichage de mon canvas, si quelqu'un sait comment s'y prendre ...
    Et sinon est-ce quelqu'un peut me confirmer qu'il n'y a pas moyen de créer des polygones remplis autrement qu'avec un objet polygon ?

  6. #6
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 9
    Points
    9
    Par défaut
    Bon j'ai trouvé comment faire pour dessiner autrement un polygone, il faut utiliser un PathFigure. J'ai donc fais un essai un peu brutal, en changeant simplement mon DataTemplate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    <DataTemplate x:Key="EntPolyLineTemplate">
               <Path Fill="Gray" Stroke="Black">
                    <Path.Data>
                        <PathGeometry>
                            <PathFigure>
                                <PathFigure.Segments>
                                    <PolyLineSegment Points="{Binding Points}" />
                                </PathFigure.Segments>
                            </PathFigure>
                        </PathGeometry>
                    </Path.Data>
                </Path>
            </DataTemplate>
    Je ne sais pas comment mesurer la différence de performance mais c'est très sensiblement ... plus lent !!! (j'ai un slider pour faire un zoom, il faut 10s pour qu'il mette à jour l'affichage au lieu de 1-2 secondes avec l'ancienne méthode).
    Peut être que je l'utilise mal ?
    En attendant je continue de chercher à rendre mon affichage asynchrone...

  7. #7
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    j'ai besoin de dessiner environ 30 000 polylines ou polygones représentant des communes dans un canvas
    Je suggérerai de créer un deuxième jeu de polygones spécifique pour les zooms qui montrent toute la carte. On peut alors supprimer un grand nombre de points composant les lignes : il s'agit des points qui, pour ces facteurs de zoom apportent une précision inutile.

    Pour l'algorithme:
    On définit un écart maxi EMax de distance entre courbe réelle et courbe réduite.
    Partant du point Pi, on cherche le point Pk (i<k) dont l'indice k est le plus grand et tel que pour tout j entre i et k (i<j<k), la distance de Pj au segment Pi-Pk est inférieure à EMax. On peut alors éliminer tous les Pj et réitérer l'opération à partir de Pk que l'on garde et ... ainsi de suite.
    __________________
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  8. #8
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 9
    Points
    9
    Par défaut
    Citation Envoyé par Graffito Voir le message
    Je suggérerai de créer un deuxième jeu de polygones spécifique pour les zooms qui montrent toute la carte. On peut alors supprimer un grand nombre de points composant les lignes : il s'agit des points qui, pour ces facteurs de zoom apportent une précision inutile.

    Pour l'algorithme:
    On définit un écart maxi EMax de distance entre courbe réelle et courbe réduite.
    Partant du point Pi, on cherche le point Pk (i<k) dont l'indice k est le plus grand et tel que pour tout j entre i et k (i<j<k), la distance de Pj au segment Pi-Pk est inférieure à EMax. On peut alors éliminer tous les Pj et réitérer l'opération à partir de Pk que l'on garde et ... ainsi de suite.
    __________________
    Bonjour Graffito merci d'avoir répondu.
    En ce qui concerne la complexité géométrique (nombre de points) de chaque entité, j'ai pu constater (en affichant juste un rectangle par entité) que cela n'influe que très peu sur les performances (le zoom est toujours aussi lent).
    Après il faudrait pouvoir regrouper plusieurs entités en une seule (par exemple la france est composée de plusieurs départements), mais problème : le format de fichier que je parse n'a pas d'informations hiérarchique, il ne s'agit que d'une suite d'entités à placer les unes à côté des autres... (pour l'instant ! Mais bon il faut que je fasse avec ).

Discussions similaires

  1. Dessiner correctement un polygone
    Par BruceBoc dans le forum OpenGL
    Réponses: 2
    Dernier message: 13/06/2007, 16h13
  2. dessiner plusieurs polygones
    Par tawsi dans le forum 2D
    Réponses: 8
    Dernier message: 30/05/2007, 13h14
  3. dessiner un polygon transparent
    Par pavlacki dans le forum Langage
    Réponses: 3
    Dernier message: 22/04/2006, 21h08
  4. [Polygon] Dessiner la surface
    Par deeal dans le forum OpenGL
    Réponses: 12
    Dernier message: 14/04/2006, 16h34
  5. dessiner lignes et polygones
    Par Harry_polin dans le forum DirectX
    Réponses: 31
    Dernier message: 25/05/2004, 17h42

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