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 :

Tracé de contour d'objet 3D : GeometryGroup


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 25
    Par défaut Tracé de contour d'objet 3D : GeometryGroup
    Bonjour,

    Je souhaiterais améliorer les performances de tracé d'un contour d'un objet 3D.

    Cela consistait au début à relier les points composant un objet 3 par 3 puis à les ranger dans une Geometry à l'aide de la méthode Geometry.Combine(..,..,GeometryCombineMode.Union). Il est cependant précisé sur MSDN que cette fonction est fortement déconseillée pour les unions car "peut nécessiter beaucoup d'UC". J'ai donc essayé de procéder comme ils le suggèrent, à l'aide de GeometryGroup. La performance est vraiment excellente (division du temps de calculs par 10 !), seulement voilà.. je n'obtient pas un contour : Nom : Contour mal tracé 1.jpg
Affichages : 709
Taille : 3,5 Ko
    Au lieu de ca : Nom : Contour bien tracé 1.jpg
Affichages : 703
Taille : 3,2 Ko

    En fait j'ai cru comprendre que l'avantage du Combine(Union) était que ca supprimait les intersections ! Pour rappel, les opérations élémentaires : Nom : geometry.jpg
Affichages : 712
Taille : 67,6 Ko

    J'ai bien essayé le Geometry.GetOulinedPathGeometry() sur chaque objet mais ca me donne un contour sur une face seulement, peu importe la rotation de l'objet. Ce n'est donc pas un vrai contour comme je souhaite : Nom : Contour GetOulinedPathGeometry.jpg
Affichages : 673
Taille : 3,4 Ko

    Auriez-vous une idée pour effectuer une opération similaire sans passer par un "combine"? En agissant sur le GeometryGroup ou en passant par autre chose..

    Merci beaucoup !

  2. #2
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour mikeycast
    Chose promise ,chose due....Je n'ai pas bien compris mais un contour d'un objet 3D peut sous entendre 2 choses...
    1/ Un "vrai" contour 3D
    -c'est le convexhull
    2/un contour 2D
    -c'est la projection de l'objet 3D sur une surface plane ("son ombre" ) sur le ViewPort3D qui une est surface 2D....malgre le "3D" accole à son nom.
    Note au passage que nos yeux font un grand travail insoupconne d'interpretation de la profondeur de vue....
    Si c'est bien un contour 2D relatif au viewport3D que tu recherches voici les etapes:
    - Obtenir une instance GeneralTransform3DTo2D relatif au ViewPort3D du ModelVisual3D courant
    -Obtient instance du Transform3DGroup applique au GeomeryModel3D
    et qui sera applique au MeshGemotry3D
    Car une instance de Mesh est toujour definie en coord. locales du Mesh (n'est pas donc affectee par le Transform3DGroup du GeomeryModel3D).....

    3/Boucler sur les Positions du MeshGeomtry
    - Appliquer le TransformGroup à chaque Position locale du Mesh
    - Appliquer GeneralTransform3DTo2D qui renvoie un Point2D relatif au ViewPort pour chaque point ainsi transforme.....
    - Recuperer les nouvelles positions modifies dans un List <Point> pts (2D)
    et creer avec un Polygon qu'on dessine sur un canvas....
    bref voici un exemple code emballe dans un user control avec:
    -un "box cube"
    -un viewport3D
    -un canvas "layer" aligne sur le Viewport3D qui servira à tracer le contour 2D...à l'aide du class Polygon..
    -un slider qui fait tourner le "box" cube et un bouton GetContour pour mettre à jour le contour 2D trace sur le canvas.....lors d'une rotation....
    code behind .cs du usercontrol:
    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
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Windows.Media.Media3D;
    namespace WpTransform3Dto2D
    {
        /// <summary>
        /// Logique d'interaction pour UserControl3.xaml
        /// </summary>
        public partial class UserControlContour2D : UserControl
        {
            private List<Point> pts;
            Rect bounds2D;
            public UserControlContour2D()
            {
                InitializeComponent();
            }
     
            private void btnContour_Click(object sender, RoutedEventArgs e)
            {
                //refresh canvas overlay
                MyCanvasOverlay.Children.Clear();
                pts = new List<Point>();
     
     
                // Recupere GeneralTransform3DTo2D relatif au viewport du ModelVisual3D
                GeneralTransform3DTo2D tt = this.MyModel.TransformToAncestor(this.MyViewport);
     
                // Recupere instance Transform3DGroup  applique au GeometryModel3D
                // qui sera applique aux positions locales  mesh
                Transform3DGroup trans3D = (Transform3DGroup)this.MyGeomModel.Transform;
     
                // Bounding Box(cadre englobant) du ModelVisual3D
                bounds2D = this.MyModel.TransformToAncestor(this.MyViewport).TransformBounds(VisualTreeHelper.GetContentBounds(this.MyModel));
     
                // Dessine  Bounding Box 2D sur canvas overlay
                Rectangle MyRectangle = new Rectangle();
                MyRectangle.Stroke = Brushes.Blue;
                MyRectangle.Width = bounds2D.Width;
                MyRectangle.Height = bounds2D.Height;
                MyCanvasOverlay.Children.Add(MyRectangle);
                Canvas.SetLeft(MyRectangle, bounds2D.X);
                Canvas.SetTop(MyRectangle, bounds2D.Y);
     
     
     
     
                /* "contour" projete  du MeshGeometry3D
                 sur la vue 2D du ViewPort   */
     
                MeshGeometry3D mesh = (MeshGeometry3D)this.MyGeomModel.Geometry;
                Point3D ptOut3D;
                for (int j = 0; j <  mesh.Positions.Count; j++)
    			{
                   /* Applique le transformGroup au positions locales du Mesh */
                   if( trans3D.TryTransform(mesh.Positions[j],out ptOut3D)) 
                   {
     
                    /* Applique GeneralTransform3DTo2D et  renvoie un Point2D relatif 
                        au ViewPort pour chaque point positions*/  
     
                       pts.Add(tt.Transform(ptOut3D));
                   }
    			}
     
                // et  dessine pts grace à un polygone  
                Polygon myPolygon = GetPolygon(pts);
                myPolygon.Stroke = Brushes.Magenta;
                myPolygon.StrokeThickness = 4.0;
                MyCanvasOverlay.Children.Add(myPolygon);
     
            }
            private Polygon GetPolygon(List<Point> pts)
            {
                Polygon myPolygon = new Polygon();
     
                myPolygon.Points.Add(pts[0]); 
                for (int i = 1; i < pts.Count; i++)
                {
     
                        myPolygon.Points.Add(pts[i]);
     
     
     
                }
                return myPolygon;
            }
        }
    }
    code xaml du usercontrol:
    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
     
    <UserControl x:Class="WpTransform3Dto2D.UserControlContour2D"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:WpTransform3Dto2D"
                >
        <UserControl.Resources>
            <local:GeometryGenerator x:Key="GeomGenerator"></local:GeometryGenerator>
        </UserControl.Resources>
     
        <StackPanel  >
            <DockPanel>
                <!-- Label Title. -->
                <Label 
                    DockPanel.Dock="Left"
                    FontSize="14" 
                    Foreground="Red" 
                    Content="Model: Cube"/>
                <!-- Button  Contour . -->
                <Button 
                    Name="btnContour"
                    FontSize="14" 
                    Foreground="Red" 
                    Content="Get Contour 2D Cube"
                    Click="btnContour_Click">
                </Button>
                <Slider 
                    DockPanel.Dock="Right" 
                    Name="rotationSlider"
                    Maximum="90"
                    Value="0">
                </Slider>
            </DockPanel>
            <!-- Viewport3D is the rendering surface. -->
            <Grid>
                <Viewport3D 
                    MinHeight="400"
                    MinWidth="540"
                    Name="MyViewport"
                    ClipToBounds="True">
                    <!-- Add a camera. -->
                    <Viewport3D.Camera>
                        <PerspectiveCamera 
                              x:Name="MyCamera"
    	                      FarPlaneDistance="100"
    	                      LookDirection="-11,-10,-9"
    	                      UpDirection="0,1,0"
    	                      NearPlaneDistance="10" 
    	                      Position="11,10,9" 
    	                      FieldOfView="25" />
                    </Viewport3D.Camera>
     
                    <!-- Add models. -->
                    <Viewport3D.Children>
                        <ModelVisual3D x:Name="MyModel" >
                            <ModelVisual3D.Content>
                                <Model3DGroup>
                                    <Model3DGroup.Children>
                                        <!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -->
                                        <DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" />
     
                                        <!-- Define a red cube. -->
                                        <GeometryModel3D 
                                            x:Name="MyGeomModel"
                                            Geometry="{Binding
                                            Source={StaticResource 
                                            GeomGenerator},
                                            Path= GeomMesh}">
                                            <GeometryModel3D.Material>
                                                <DiffuseMaterial>
                                                    <DiffuseMaterial.Brush>
                                                        <SolidColorBrush 
                                                            Color="Red" 
                                                            Opacity="1.0"/>
                                                    </DiffuseMaterial.Brush>
                                                </DiffuseMaterial>
                                            </GeometryModel3D.Material>
                                            <GeometryModel3D.Transform>
                                                <Transform3DGroup>
                                                    <RotateTransform3D>
                                                        <RotateTransform3D.Rotation>
                                                            <AxisAngleRotation3D
                                                                 x:Name="MyRotation"
                                                                 Axis="0,1,0"
    												             Angle="{Binding ElementName=rotationSlider,Path=Value}" />
                                                        </RotateTransform3D.Rotation>
                                                    </RotateTransform3D>
                                                    <TranslateTransform3D />
                                                </Transform3DGroup>
                                            </GeometryModel3D.Transform>
                                        </GeometryModel3D>
     
                                        <DirectionalLight 
    	                                    Color="White" 
    	                                    Direction="-2,-3,-1" />
                                    </Model3DGroup.Children>
                                </Model3DGroup>
                            </ModelVisual3D.Content>
                        </ModelVisual3D>
                    </Viewport3D.Children>
                </Viewport3D>
                <Canvas
                    Name="MyCanvasOverlay"   >
                </Canvas>
            </Grid>
        </StackPanel>
     
    </UserControl>
    code behind .cs du generateur du "box cube":
    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.Windows.Media.Media3D;
    using System.Windows.Media;
    namespace WpTransform3Dto2D
    { 
        public class GeometryGenerator
        {
            public  GeometryGenerator()
            {
                GeomMesh = CreateCubeModel();
     
            }
            public MeshGeometry3D GeomMesh { get; set; }
            public static MeshGeometry3D CreateCubeModel()
            {
                MeshGeometry3D mesh = new MeshGeometry3D();
     
                mesh.Positions.Add(new Point3D(-1, -1, 1));
                mesh.Positions.Add(new Point3D(1, -1, 1));
                mesh.Positions.Add(new Point3D(1, 1, 1));
                mesh.Positions.Add(new Point3D(-1, 1, 1));
                mesh.TriangleIndices.Add(0);
                mesh.TriangleIndices.Add(1);
                mesh.TriangleIndices.Add(2);
                mesh.TriangleIndices.Add(0);
                mesh.TriangleIndices.Add(2);
                mesh.TriangleIndices.Add(3);
                mesh.Normals.Add(new Vector3D(0, 0, 1));
                mesh.Normals.Add(new Vector3D(0, 0, 1));
                mesh.Normals.Add(new Vector3D(0, 0, 1));
                mesh.Normals.Add(new Vector3D(0, 0, 1));
     
                mesh.Positions.Add(new Point3D(1, -1, 1));
                mesh.Positions.Add(new Point3D(1, -1, -1));
                mesh.Positions.Add(new Point3D(1, 1, -1));
                mesh.Positions.Add(new Point3D(1, 1, 1));
                mesh.TriangleIndices.Add(4);
                mesh.TriangleIndices.Add(5);
                mesh.TriangleIndices.Add(6);
                mesh.TriangleIndices.Add(4);
                mesh.TriangleIndices.Add(6);
                mesh.TriangleIndices.Add(7);
                mesh.Normals.Add(new Vector3D(1, 0, 0));
                mesh.Normals.Add(new Vector3D(1, 0, 0));
                mesh.Normals.Add(new Vector3D(1, 0, 0));
                mesh.Normals.Add(new Vector3D(1, 0, 0));
     
                mesh.Positions.Add(new Point3D(1, -1, -1));
                mesh.Positions.Add(new Point3D(-1, -1, -1));
                mesh.Positions.Add(new Point3D(-1, 1, -1));
                mesh.Positions.Add(new Point3D(1, 1, -1));
                mesh.TriangleIndices.Add(8);
                mesh.TriangleIndices.Add(9);
                mesh.TriangleIndices.Add(10);
                mesh.TriangleIndices.Add(8);
                mesh.TriangleIndices.Add(10);
                mesh.TriangleIndices.Add(11);
                mesh.Normals.Add(new Vector3D(0, 0, -1));
                mesh.Normals.Add(new Vector3D(0, 0, -1));
                mesh.Normals.Add(new Vector3D(0, 0, -1));
                mesh.Normals.Add(new Vector3D(0, 0, -1));
     
                mesh.Positions.Add(new Point3D(-1, -1, -1));
                mesh.Positions.Add(new Point3D(-1, -1, 1));
                mesh.Positions.Add(new Point3D(-1, 1, 1));
                mesh.Positions.Add(new Point3D(-1, 1, -1));
                mesh.TriangleIndices.Add(12);
                mesh.TriangleIndices.Add(13);
                mesh.TriangleIndices.Add(14);
                mesh.TriangleIndices.Add(12);
                mesh.TriangleIndices.Add(14);
                mesh.TriangleIndices.Add(15);
                mesh.Normals.Add(new Vector3D(-1, 0, 0));
                mesh.Normals.Add(new Vector3D(-1, 0, 0));
                mesh.Normals.Add(new Vector3D(-1, 0, 0));
                mesh.Normals.Add(new Vector3D(-1, 0, 0));
     
                mesh.Positions.Add(new Point3D(-1, -1, 1));
                mesh.Positions.Add(new Point3D(-1, -1, -1));
                mesh.Positions.Add(new Point3D(1, -1, -1));
                mesh.Positions.Add(new Point3D(1, -1, 1));
                mesh.TriangleIndices.Add(16);
                mesh.TriangleIndices.Add(17);
                mesh.TriangleIndices.Add(18);
                mesh.TriangleIndices.Add(16);
                mesh.TriangleIndices.Add(18);
                mesh.TriangleIndices.Add(19);
                mesh.Normals.Add(new Vector3D(0, -1, 0));
                mesh.Normals.Add(new Vector3D(0, -1, 0));
                mesh.Normals.Add(new Vector3D(0, -1, 0));
                mesh.Normals.Add(new Vector3D(0, -1, 0));
     
                mesh.Positions.Add(new Point3D(-1, 1, 1));
                mesh.Positions.Add(new Point3D(1, 1, 1));
                mesh.Positions.Add(new Point3D(1, 1, -1));
                mesh.Positions.Add(new Point3D(-1, 1, -1));
                mesh.TriangleIndices.Add(20);
                mesh.TriangleIndices.Add(21);
                mesh.TriangleIndices.Add(22);
                mesh.TriangleIndices.Add(20);
                mesh.TriangleIndices.Add(22);
                mesh.TriangleIndices.Add(23);
                mesh.Normals.Add(new Vector3D(0, 1, 0));
                mesh.Normals.Add(new Vector3D(0, 1, 0));
                mesh.Normals.Add(new Vector3D(0, 1, 0));
                mesh.Normals.Add(new Vector3D(0, 1, 0));
     
     
                return mesh;
     
            }
     
        }
    }
    code xamL du simplistic winform:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <Window x:Class="WpTransform3Dto2D.WindowContour2D"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpTransform3Dto2D"
            Title="Contour2D" Height="300" Width="300">
        <Grid>
            <local:UserControlContour2D></local:UserControlContour2D>
        </Grid>
    </Window>
    En esperant qu'il reponde au souci........

    A propos des Tasks bonne nouvelle pour toi:
    - le .Net FrameWork 4.5 donc VS2011 ou VS2012
    dispose du class static BindingOperations.EnableCollectionSynchronization qui permet un acces multi-thread aux ....ObservableCollection du ViewModel.(plus besoin du Dispatcher UI).
    Il sufit d'une ligne de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    private static object _itemsLock = new object();  
    private ObservableCollection<string> _items = new ObservableCollection<string>();  
    public ObservableCollection<string> Items { get { return _items; } }  
    public MainWindow()  
    {  
     
         InitializeComponent();  
         BindingOperations.EnableCollectionSynchronization(_items, _itemsLock);  
     
    }
    Si tu n'as pas VS2011 alors comme moi j'ai le .Net Framework 4.0 donc VS2010 on a quand meme les BlockingCollection(spacename using System.Collections.Concurrent) qui gerent l'acces multi-thread...
    Mais il faut :
    -recopier l'ObservableCollection avec une boucle dans un BlockingCollection(T) (et ceci s'applique à toute collection sous-reference à laquelle tu accedes dans un Task thread y compris les natives comme Pisitions,Vertices et tutti quanti....)................

    bon code................

  3. #3
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 25
    Par défaut
    Bonjour Mabrouki,

    merci beaucoup pour ta réponse très complète ! Pour répondre à ta première question, je veux bien entendu tracer un contour sur le Viewport3D, c'est-à-dire sur le plan 2D !
    J'ai essayé ton code et malheureusement ça ne correspond pas bien à ce que je veux. Ton code trace le contour de toutes les arrêtes du cube, mais je souhaite uniquement avoir le contour extérieur ! En d'autres mots, "La plus grande figure qui englobe tout le cube", c'est la deuxième image que j'ai mis dans mon post, alors que ton code me donne : Nom : ContourCube.jpg
Affichages : 914
Taille : 54,2 Ko

    A mon avis ton code est performant comme il le faut, mais il faut trouver le moyen de "vider l'intérieur du cube", c'est-à-dire enlever les arrêtes qui sont à l'intérieur.

    As-tu une idée pour arriver à cela?

  4. #4
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour mickeycast....
    D'abord on ne peut pas dessiner des objets 2D sur le ViewPort3D avec l'api WPF actuelle.... c'est un "lack" de wpf..
    Il n' y a aucune commande en WPF pour dire au ViewPort3D trace un mesh entre 2 points 3D (x,y,z)

    Pourtant on peut dessiner en 3D les aretes qu'on veut sur le ViewPort3D mais avec un "wireframe" (en francais une cage 3D).
    C'est ce que nombre de logiciels DAO font couramment.
    Pour combler ce "lack" il y a 2 ToolKit WPF:
    -3D Tools sur le site Microsoft CodePlex.Com qui permet grace à son class ScreenSpaceLines3D de generer le "wireframe" 3D dans le ViewPort3D et de dessiner par exemple les axes ou les normales (1er exemple de code).....

    -Petzold.Media3D librairie avec code source sur le site de l'auteur Charles Petzold (un mentor de Microsoft) que je prefere car plus riche(class WireFrame,WirePolyline, WireLine ,et meme...... WirePath et WireText si on ecrit du texte au point3d(x,y,z) du VP).....bref un arsenal de guerre.....
    (2er exemple de code ).....

    Le class ScreenSpaceLines3D aussi bien que les class "wire" de Petzold.Media disposent de la collection Points.....pour les points du trace...

    Autre point important :
    -le wireframe cree (cage) est ajoute simplement à ViewPort3d.Children quoique n'etant pas un Model3D....simplistic....
    Maintenant pour dessiner uniquement ce qui est autour c'est subtil car tu oublies que si le model est en mouvement(rotation) c'est difficile :
    - de defnir les points à l'interieur car ils changes constamment .....
    - c'est pour cela que je dessine tout ....
    Exemple du cube:quelque soit la position au cours du temps(rotation) on voit constamment 4 sommets +1 sommet central(cube a 6 sommets)
    Mais..... qui ne sont pas les memes d'ou la difficulte de definir les sommets du contour.....C'est pour cela que j'ai parle d' "ombre" (c'est presque l'adage prendre l'ombre pour la proie)......

    bref voici :
    1er code exemple pour 3DTools:
    code behind.cs du winform :
    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
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Windows.Media.Media3D;
    //ScreenSpaceLines3D Class
    using _3DTools;
    namespace WpfWireFrame3D
    {
        /// <summary>
        /// Logique d'interaction pour MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
     
            private void cubeButtonClick(object sender, RoutedEventArgs e)
            {
                Model3DGroup cube = new Model3DGroup();
                Point3D p0 = new Point3D(0, 0, 0);
                Point3D p1 = new Point3D(5, 0, 0);
                Point3D p2 = new Point3D(5, 0, 5);
     
                Point3D p3 = new Point3D(0, 0, 5);
                Point3D p4 = new Point3D(0, 5, 0);
                Point3D p5 = new Point3D(5, 5, 0);
     
                Point3D p6 = new Point3D(5, 5, 5);
                Point3D p7 = new Point3D(0, 5, 5);
                //front side triangles
                cube.Children.Add(CreateTriangleModel(p3, p2, p6));
                cube.Children.Add(CreateTriangleModel(p3, p6, p7));
                //right side triangles
                cube.Children.Add(CreateTriangleModel(p2, p1, p5));
                cube.Children.Add(CreateTriangleModel(p2, p5, p6));
                //back side triangles
                cube.Children.Add(CreateTriangleModel(p1, p0, p4));
                cube.Children.Add(CreateTriangleModel(p1, p4, p5));
                //left side triangles
                cube.Children.Add(CreateTriangleModel(p0, p3, p7));
                cube.Children.Add(CreateTriangleModel(p0, p7, p4));
                //top side triangles
                cube.Children.Add(CreateTriangleModel(p7, p6, p5));
                cube.Children.Add(CreateTriangleModel(p7, p5, p4));
                //bottom side triangles
                cube.Children.Add(CreateTriangleModel(p2, p3, p0));
                cube.Children.Add(CreateTriangleModel(p2, p0, p1));
     
                ModelVisual3D model = new ModelVisual3D();
                model.Content = cube;
     
                //ATTENTION APPLIQUER LE TRANSFORM AU MODEL CUBE  
                model.Transform = this.myRotation;
     
                this.mainViewport.Children.Add(model);
     
            }
     
     
            //abstract your model model mesh
            private Model3DGroup CreateTriangleModel(Point3D p0, Point3D p1, Point3D p2)
            {
                MeshGeometry3D mesh = new MeshGeometry3D();
                mesh.Positions.Add(p0);
                mesh.Positions.Add(p1);
                mesh.Positions.Add(p2);
                mesh.TriangleIndices.Add(0);
                mesh.TriangleIndices.Add(1);
                mesh.TriangleIndices.Add(2);
                Vector3D normal = CalculateNormal(p0, p1, p2);
                mesh.Normals.Add(normal);
                mesh.Normals.Add(normal);
                mesh.Normals.Add(normal);
                Material material = new DiffuseMaterial(
                    new SolidColorBrush(Colors.DarkKhaki));
                GeometryModel3D model = new GeometryModel3D(
                    mesh, material);
                Model3DGroup group = new Model3DGroup();
                group.Children.Add(model);
     
                // creer les droites normales en "2D" oui?
                if (normalsCheckBox.IsChecked == true)
                    group.Children.Add(BuildNormals(p0, p1, p2, normal));
     
                // creer le "wirefram" qui fera ton bonheur peut etre
                if (wireframeCheckBox.IsChecked == true)
                {
                    ScreenSpaceLines3D wireframe = new ScreenSpaceLines3D();
                    wireframe.Points.Add(p0);
                    wireframe.Points.Add(p1);
                    wireframe.Points.Add(p2);
                    wireframe.Points.Add(p0);
                    wireframe.Color = Colors.LightBlue;
                    wireframe.Thickness = 3;
                    //ATTENTION  APPLIQUER LE MEME TRANSFORM AU "WIREFRAME"  
                    wireframe.Transform = this.myRotation;
                    this.mainViewport.Children.Add(wireframe);
                }
     
                return group;
            }
            private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2)
            {
                Vector3D v0 = new Vector3D(
                    p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
                Vector3D v1 = new Vector3D(
                    p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
                return Vector3D.CrossProduct(v0, v1);
            }
     
            // builds normals
            private Model3DGroup BuildNormals(
                Point3D p0,
                Point3D p1,
                Point3D p2,
                Vector3D normal)
            {
                Model3DGroup normalGroup = new Model3DGroup();
                Point3D p;
                ScreenSpaceLines3D normal0Wire = new ScreenSpaceLines3D();
                ScreenSpaceLines3D normal1Wire = new ScreenSpaceLines3D();
                ScreenSpaceLines3D normal2Wire = new ScreenSpaceLines3D();
                Color c = Colors.Blue;
                int width = 1;
                normal0Wire.Thickness = width;
                normal0Wire.Color = c;
                normal1Wire.Thickness = width;
                normal1Wire.Color = c;
                normal2Wire.Thickness = width;
                normal2Wire.Color = c;
                double num = 1;
                double mult = .01;
                double denom = mult * Convert.ToDouble(normalSizeTextBox.Text);
                double factor = num / denom;
                p = Vector3D.Add(Vector3D.Divide(normal, factor), p0);
                normal0Wire.Points.Add(p0);
                normal0Wire.Points.Add(p);
                p = Vector3D.Add(Vector3D.Divide(normal, factor), p1);
                normal1Wire.Points.Add(p1);
                normal1Wire.Points.Add(p);
                p = Vector3D.Add(Vector3D.Divide(normal, factor), p2);
                normal2Wire.Points.Add(p2);
                normal2Wire.Points.Add(p);
     
                //Normal wires are not models, so we can't
                //add them to the normal group.  Just add them
                //to the viewport for now...
     
                this.mainViewport.Children.Add(normal0Wire);
                this.mainViewport.Children.Add(normal1Wire);
                this.mainViewport.Children.Add(normal2Wire);
     
                return normalGroup;
            }
     
        }
    }
    code xaml du winform:
    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
     
     
    <Window x:Class="WpfWireFrame3D.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <DockPanel 
                  Width="Auto" 
                  VerticalAlignment="Stretch" 
                  Height="Auto" 
                  HorizontalAlignment="Stretch" 
                  Grid.ColumnSpan="1" 
                  Grid.Column="0" 
                  Grid.Row="0" 
                  Margin="0,0,0,0" 
                  Grid.RowSpan="1">
                <StackPanel>
                    <StackPanel.Background>
                        <LinearGradientBrush>
                            <GradientStop Color="White" Offset="0"/>
                            <GradientStop Color="DarkKhaki" Offset=".3"/>
                            <GradientStop Color="DarkKhaki" Offset=".7"/>
                            <GradientStop Color="White" Offset="1"/>
                        </LinearGradientBrush>
                    </StackPanel.Background>
                    <StackPanel Margin="10">
                        <Button 
                            Name="cubeButton" 
                            Click="cubeButtonClick"
                            Content="Cube">
                        </Button>
                        <Separator/>
                        <CheckBox Name="wireframeCheckBox"
                                  Content="Show Wireframe">
                        </CheckBox>
                        <Separator/>
                        <CheckBox Name="normalsCheckBox"
                                  Content="Show Normals">
                        </CheckBox>
                        <TextBlock Text="Normal Size:"/>
                        <TextBox Name="normalSizeTextBox" Text="1"/>
                        <Slider 
                            Name="sliderRotation"
                            Minimum="0"
                            Maximum="360"
                            Value="0">
                        </Slider>
                    </StackPanel>
                </StackPanel>
                <Viewport3D 
                    Name="mainViewport" 
                    ClipToBounds="True">
                    <Viewport3D.Camera>
                        <PerspectiveCamera 
    	                  FarPlaneDistance="100"
    	                  LookDirection="-11,-10,-9"
    	                  UpDirection="0,1,0"
    	                  NearPlaneDistance="1" 
    	                  Position="11,10,9" 
    	                  FieldOfView="70" />
                    </Viewport3D.Camera>
                    <ModelVisual3D>
                        <ModelVisual3D.Transform>
                            <RotateTransform3D   x:Name="myRotation">
                                <RotateTransform3D.Rotation>
                                    <AxisAngleRotation3D
                                        Angle="{Binding ElementName=sliderRotation,Path=Value}"
                                        Axis="0,1,0"/>                 
                                </RotateTransform3D.Rotation>
                            </RotateTransform3D>
                        </ModelVisual3D.Transform>
                        <ModelVisual3D.Content>
                            <DirectionalLight 
    	                        Color="White" 
    	                        Direction="-2,-3,-1" />
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                </Viewport3D>
            </DockPanel>
        </Grid>
    </Window>
    2er code exemple pour Petzold.Media3D
    bien plus simple.....
    code behind.cs du winform :
    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
     
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Windows.Media.Media3D;
    //WireFrame Class de la lib  Petzold.Media3D
    using Petzold.Media3D;
    namespace WpfWireFrame3D
    {
        /// <summary>
        /// Logique d'interaction pour Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            Petzold.Media3D.WireFrame wire;
     
            public Window1()
            {
                InitializeComponent();
     
            }
     
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                MeshGeometry3D mesh3D = this.meshMain;
                wire = new WireFrame();
                wire.Rounding = 10;
                wire.Thickness = 2;
                wire.Color = Colors.LightBlue;
                wire.Positions = mesh3D.Positions;
                wire.TriangleIndices = mesh3D.TriangleIndices;
                wire.TextureCoordinates = mesh3D.TextureCoordinates;
                wire.Normals = mesh3D.Normals;
                //ATTENTION  APPLIQUER LE MEME TRANSFORM AU "WIREFRAME"  
                wire.Transform = this.mainModel.Transform;
                this.mainViewport3D.Children.Add(wire);
            }
        }
    }
    code xaml du winform
    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
     
    <Window x:Class="WpfWireFrame3D.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window1" Height="300" Width="300"
            Loaded="Window_Loaded">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <Slider 
                Name="sliderRotation"
                Minimum="0"
                Maximum="360"
                Value="0">
            </Slider>
            <Viewport3D 
                Grid.Row="1"
                Name="mainViewport3D"
                ClipToBounds="True"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch">
                <Viewport3D.Camera>
                    <PerspectiveCamera x:Name="camMain" Position="6 5 4" LookDirection="-6 -5 -4">
                        </PerspectiveCamera>
                </Viewport3D.Camera>
                <ModelVisual3D>
                    <ModelVisual3D.Content>
                        <DirectionalLight x:Name="dirLightMain" Direction="-1,-1,-1">
                           </DirectionalLight>
                    </ModelVisual3D.Content>
                </ModelVisual3D>
                <ModelVisual3D  x:Name="mainModel">
                    <ModelVisual3D.Transform>
                        <RotateTransform3D   x:Name="myRotation">
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D
                                        Angle="{Binding ElementName=sliderRotation,Path=Value}"
                                        Axis="0,1,0"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                    </ModelVisual3D.Transform>
                    <ModelVisual3D.Content>
                        <GeometryModel3D  >
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D
                                    x:Name="meshMain" 
                                     Positions="0 0 0  1 0 0  0 1 0  1 1 0  0 0 1  1 0 1  0 1 1  1 1 1" 
                                     TriangleIndices="2 3 1  2 1 0  7 1 3  7 5 1  6 5 7  6 4 5  6 2 0  2 0 4  2 7 3  2 6 7  0 1 5  0 5 4">
                                </MeshGeometry3D>
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial x:Name="matDiffuseMain">
                                    <DiffuseMaterial.Brush>
                                        <SolidColorBrush Color="Red"/>
                                    </DiffuseMaterial.Brush>
                                </DiffuseMaterial>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>
                    </ModelVisual3D.Content>
                </ModelVisual3D>
            </Viewport3D>
        </Grid> 
    </Window>
    lien 3DTools codeplex:

    http://www.codeplex.com/3DTools

    -----------------------------------------------------------------
    lien Petzold.Media site (auteur Microsoft):
    http://www.charlespetzold.com/blog/2007/08/310158.html

    bon code.....................

  5. #5
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Août 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2012
    Messages : 25
    Par défaut
    Bonjour Mabrouki,

    J'ai cru comprendre que les deux exemples de bibliothèques que tu me donnais permettent de mieux manipuler le "wireframe", la cage 3d, mais qu'au final je ne pourrais quand même pas tracer les contours car c'est compliqué.

    On m'a donné une idée qui me semble pas mal, et qui est de tracé deux "wireframes" et de réduire un petit peu la taille de la deuxième. Ensuite, on fait une opération de soustraction (la première moins la deuxième) qui revient à supprimer tout ce qu'il y a à l'intérieur de la première !

    Comme je ne connais vraiment pas la manipulation du viewport et des bibliothèques que tu m'as donné, aurais tu une idée des manières de mettre en place ce que j'avance?

    Et aussi ton avis sur son fonctionnement?

    Vraiment merci à toi

  6. #6
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour mickeycast
    C'est une bonne idee mais qui n'as aucun sens dans WPF car il ne supporte pas les operations booleenes ni sur les solides Model3D ni à fortiori sur les "wires" frames des biblio citees
    Car elles sont basees sur les Model3D de wpf.....
    Bon code...........

Discussions similaires

  1. Contours d'objet après triangulation
    Par enita dans le forum MATLAB
    Réponses: 3
    Dernier message: 28/06/2011, 17h37
  2. Tracé de contours (outlining)
    Par pottiez dans le forum Contribuez
    Réponses: 0
    Dernier message: 03/01/2011, 14h47
  3. Trier des vertices pour tracé de contour
    Par Djakisback dans le forum Algorithmes et structures de données
    Réponses: 22
    Dernier message: 12/06/2010, 13h46
  4. Tracé de contour dans des tableaux
    Par airballman dans le forum Calcul scientifique
    Réponses: 4
    Dernier message: 17/07/2009, 09h03
  5. tracé d'un contour
    Par Omfraax dans le forum OpenGL
    Réponses: 13
    Dernier message: 06/03/2006, 21h42

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