Bonjour à tous,
Je voudrais afficher un graphe 3d, je pense que le pack visual studio d'origine ne le permet pas.
En cherchant je ne suis tombé que sur des choses qui paraissent très performantes et compliqués.
Quelles sont vos conseils?
Bonjour à tous,
Je voudrais afficher un graphe 3d, je pense que le pack visual studio d'origine ne le permet pas.
En cherchant je ne suis tombé que sur des choses qui paraissent très performantes et compliqués.
Quelles sont vos conseils?
bonjour
regarde sur ce lien de developpez.net il y a un cours de Philippe Laserre sur le controle Chart 4.0 de VS 2010 que tu dois avoir dans ta boite à outils..
http://www.google.fr/url?sa=t&source...eUd2pxLL27u8gQ
Bon code................
bonjour Gualino
le dessin d'une surface veux-tu dire car z=f(x,y) definit une surface en 3 dimensions et u=f(x,y,z) un solide.
Il faut voir les third-party control pour WPF ou l'on peut faire de l'affichage en 3D et meme de l'animation.
bon code.........
bonjour Pol63
Bah j'ai bien dit Control Tiers et payant .Je n'ai pas dit le Microsoft Data Visualisation WPF de Visual Studio qui ne fait que des graphs 2D.
Meme en WPF encore faut-il coder aussi bien les surfaces de base elementaires a l'aide de triangles(triangles sommets,indices, et coord. textures) et idem pour les solides de base (cube,sphere et autre cylindre....).
Pour Gualino maintenant voici un avant-gout de ce que tu peux faire en matiere de surface .
Exemple code en csharp(tu peux translater aisement en vb.net car moi je fait plus VB.Net que CSharp):
- 1er exemple c'est une classe surface parametre simple nommee SimpleSurface
- 2e exemple c'est une classe surface parametre plus complexe nommee ParametricSurface .
-Il y a en plus une classe appelee Utility sa fonction est de creer un rectangle elementaire car finalement ta surface est une grille en 3D a base de rectangles elementaires.Elle est dote de 3 fonctions:
1/ Creer la "Face" du rectangle pour eclairage en 3D(sinon invisible)
2/"Wireframe ou Mesh ou "maillage en francais" du rectangle (4 cotes) (parce avec l'Api WPF il 2 triangles juxtaposes=1 rectangle)
3/GetNormalized pour transformer tes coord. reels x,y,z vers des coord. d'ecran (-1,1).
code behind classe commune Utility :
EXEMPLE1
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 using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Controls; //necessaire using _3DTools; namespace WpfAppSurfaceCS { public class Utility { public static void CreateRectangleFace(Point3D p0, Point3D p1, Point3D p2, Point3D p3, Color surfaceColor, Viewport3D viewport) { MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.Positions.Add(p3); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(0); SolidColorBrush brush = new SolidColorBrush(); brush.Color = surfaceColor; Material material = new DiffuseMaterial(brush); GeometryModel3D geometry = new GeometryModel3D(mesh, material); ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; viewport.Children.Add(model); } public static void CreateWireframe(Point3D p0, Point3D p1, Point3D p2, Point3D p3, Color lineColor, Viewport3D viewport) { //cette class appartient à lib 3DTools ScreenSpaceLines3D ssl = new ScreenSpaceLines3D(); ssl.Points.Add(p0); ssl.Points.Add(p1); ssl.Points.Add(p1); ssl.Points.Add(p2); ssl.Points.Add(p2); ssl.Points.Add(p3); ssl.Points.Add(p3); ssl.Points.Add(p0); ssl.Color = lineColor; ssl.Thickness = 2; viewport.Children.Add(ssl); } public static Point3D GetNormalize(Point3D pt,double xmin, double xmax, double ymin, double ymax,double zmin, double zmax) { pt.X = -1 + 2 * (pt.X - xmin) / (xmax - xmin); pt.Y = -1 + 2 * (pt.Y - ymin) / (ymax - ymin); pt.Z = -1 + 2 * (pt.Z - zmin) / (zmax - zmin); return pt; } } }
code behind classe SimpleSurface :
code behind fenetre WinSimpleSurfaceTest :
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 using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Controls; namespace WpfAppSurfaceCS { public class SimpleSurface { public delegate Point3D Function(double x, double z); private double xmin = -3; private double xmax = 3; private double ymin = -8; private double ymax = 8; private double zmin = -3; private double zmax = 3; private int nx = 30; private int nz = 30; private Color lineColor = Colors.Black; private Color surfaceColor = Colors.White; private Point3D center = new Point3D(); private bool isHiddenLine = false; private bool isWireframe = true; private Viewport3D viewport3d = new Viewport3D(); public bool IsWireframe { get { return isWireframe; } set { isWireframe = value; } } public bool IsHiddenLine { get { return isHiddenLine; } set { isHiddenLine = value; } } public Color LineColor { get { return lineColor; } set { lineColor = value; } } public Color SurfaceColor { get { return surfaceColor; } set { surfaceColor = value; } } public double Xmin { get { return xmin; } set { xmin = value; } } public double Xmax { get { return xmax; } set { xmax = value; } } public double Ymin { get { return ymin; } set { ymin = value; } } public double Ymax { get { return ymax; } set { ymax = value; } } public double Zmin { get { return zmin; } set { zmin = value; } } public double Zmax { get { return zmax; } set { zmax = value; } } public int Nx { get { return nx; } set { nx = value; } } public int Nz { get { return nz; } set { nz = value; } } public Point3D Center { get { return center; } set { center = value; } } public Viewport3D Viewport3d { get { return viewport3d; } set { viewport3d = value; } } public void CreateSurface(Function f) { double dx = (Xmax - Xmin) / Nx; double dz = (Zmax - Zmin) / Nz; if (Nx < 2 || Nz < 2) return; Point3D[,] pts = new Point3D[Nx, Nz]; for (int i = 0; i < Nx; i++) { double x = Xmin + i * dx; for (int j = 0; j < Nz; j++) { double z = Zmin + j * dz; pts[i, j] = f(x, z); pts[i, j] += (Vector3D)Center; pts[i, j] = Utility.GetNormalize( pts[i, j], Xmin, Xmax, Ymin, Ymax, Zmin, Zmax); } } Point3D[] p = new Point3D[4]; for (int i = 0; i < Nx - 1; i++) { for (int j = 0; j < Nz - 1; j++) { p[0] = pts[i, j]; p[1] = pts[i, j + 1]; p[2] = pts[i + 1, j + 1]; p[3] = pts[i + 1, j]; //Create rectangular face: if (IsHiddenLine == false) Utility.CreateRectangleFace( p[0], p[1], p[2], p[3], SurfaceColor, Viewport3d); // Create wireframe: if (IsWireframe == true) Utility.CreateWireframe( p[0], p[1], p[2], p[3], LineColor, Viewport3d); } } } } }
code xaml fenetre WinSimpleSurfaceTest:
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 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.Media3D; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfAppSurfaceCS { /// <summary> /// Logique d'interaction pour Window1.xaml /// </summary> public partial class WinSimpleSurfaceTest : Window { private SimpleSurface ss = new SimpleSurface(); public WinSimpleSurfaceTest() { InitializeComponent(); ss.IsHiddenLine = false; ss.Viewport3d = viewport; AddSinc(); } private void AddSinc() { ss.Xmin = -8; ss.Xmax = 8; ss.Zmin = -8; ss.Zmax = 8; ss.Ymin = -1; ss.Ymax = 1; ss.CreateSurface(Sinc); } private Point3D Sinc(double x, double z) { double r = Math.Sqrt(x * x + z * z) + 0.00001; double y = Math.Sin(r) / r; return new Point3D(x, y, z); } } }
EXEMPLE2:
Code xaml : 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 <Window x:Class="WpfAppSurfaceCS.WinSimpleSurfaceTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Simple Surface Test" Height="300" Width="300"> <Grid> <Viewport3D Name="viewport"> <Viewport3D.Camera> <PerspectiveCamera Position="3,3,2" LookDirection="-3,-3,-2" UpDirection="0,1,0"/> </Viewport3D.Camera> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <AmbientLight Color="White"/> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D> </Grid> </Window>
code behind classe ParametricSurface :
code behind fenetre WinParametricSurfaceTest
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 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Controls; namespace WpfAppSurfaceCS { class ParametricSurface { public delegate Point3D Function(double u, double v); private int nu = 30; private int nv = 30; private double umin = -3; private double umax = 3; private double vmin = -8; private double vmax = 8; private double xmin = -1; private double xmax = 1; private double ymin = -1; private double ymax = 1; private double zmin = -1; private double zmax = 1; private Color lineColor = Colors.Black; private Color surfaceColor = Colors.White; private Point3D center = new Point3D(); private bool isHiddenLine = false; private bool isWireframe = true; private Viewport3D viewport3d = new Viewport3D(); public bool IsWireframe { get { return isWireframe; } set { isWireframe = value; } } public bool IsHiddenLine { get { return isHiddenLine; } set { isHiddenLine = value; } } public Color LineColor { get { return lineColor; } set { lineColor = value; } } public Color SurfaceColor { get { return surfaceColor; } set { surfaceColor = value; } } public double Umin { get { return umin; } set { umin = value; } } public double Umax { get { return umax; } set { umax = value; } } public double Vmin { get { return vmin; } set { vmin = value; } } public double Vmax { get { return vmax; } set { vmax = value; } } public int Nu { get { return nu; } set { nu = value; } } public int Nv { get { return nv; } set { nv = value; } } public double Xmin { get { return xmin; } set { xmin = value; } } public double Xmax { get { return xmax; } set { xmax = value; } } public double Ymin { get { return ymin; } set { ymin = value; } } public double Ymax { get { return ymax; } set { ymax = value; } } public double Zmin { get { return zmin; } set { zmin = value; } } public double Zmax { get { return zmax; } set { zmax = value; } } public Point3D Center { get { return center; } set { center = value; } } public Viewport3D Viewport3d { get { return viewport3d; } set { viewport3d = value; } } public void CreateSurface(Function f) { double du = (Umax - Umin) / (Nu - 1); double dv = (Vmax - Vmin) / (Nv - 1); if (Nu < 2 || Nv < 2) return; Point3D[,] pts = new Point3D[Nu, Nv]; for (int i = 0; i < Nu; i++) { double u = Umin + i * du; for (int j = 0; j < Nv; j++) { double v = Vmin + j * dv; pts[i, j] = f(u, v); pts[i, j] += (Vector3D)Center; pts[i, j] = Utility.GetNormalize( pts[i, j], Xmin, Xmax, Ymin, Ymax, Zmin, Zmax); } } Point3D[] p = new Point3D[4]; for (int i = 0; i < Nu - 1; i++) { for (int j = 0; j < Nv - 1; j++) { p[0] = pts[i, j]; p[1] = pts[i, j + 1]; p[2] = pts[i + 1, j + 1]; p[3] = pts[i + 1, j]; //Create rectangular face: if (IsHiddenLine == false) Utility.CreateRectangleFace( p[0], p[1], p[2], p[3], SurfaceColor, Viewport3d); // Create wireframe: if (IsWireframe == true) Utility.CreateWireframe( p[0], p[1], p[2], p[3], LineColor, Viewport3d); } } } } }
code xaml de la fenetre WinParametricSurfaceTest :
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 using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace WpfAppSurfaceCS { /// <summary> /// Logique d'interaction pour ParametricSurfaceTest.xaml /// </summary> public partial class ParametricSurfaceTest : Window { private ParametricSurface ps = new ParametricSurface(); public ParametricSurfaceTest() { InitializeComponent(); ps.IsHiddenLine = false; ps.Viewport3d = viewport; //AddHelicoid(); AddSphere(); } private void AddHelicoid() { ps.Umin = 0; ps.Umax = 1; ps.Vmin = -3 * Math.PI; ps.Vmax = 3 * Math.PI; ps.Nv = 100; ps.Nu = 10; ps.Ymin = ps.Vmin; ps.Ymax = ps.Vmax; ps.CreateSurface(Helicoid); } private Point3D Helicoid(double u, double v) { double x = u * Math.Cos(v); double z = u * Math.Sin(v); double y = v; return new Point3D(x, y, z); } private void AddSphere() { ps.Umin = 0; ps.Umax = 2 * Math.PI; ps.Vmin = -0.5 * Math.PI; ps.Vmax = 0.5 * Math.PI; ps.Nu = 20; ps.Nv = 20; ps.CreateSurface(Sphere); } private Point3D Sphere(double u, double v) { double x = Math.Cos(v) * Math.Cos(u); double z = Math.Cos(v) * Math.Sin(u); double y = Math.Sin(v); return new Point3D(x, y, z); } private void AddTorus() { ps.Umin = 0; ps.Umax = 2 * Math.PI; ps.Vmin = 0; ps.Vmax = 2 * Math.PI; ps.Nu = 50; ps.Nv = 20; ps.CreateSurface(Torus); } private Point3D Torus(double u, double v) { double x = (1 + 0.3 * Math.Cos(v)) * Math.Cos(u); double z = (1 + 0.3 * Math.Cos(v)) * Math.Sin(u); double y = 0.3 * Math.Sin(v); return new Point3D(x, y, z); } } }
NB: pour que l' exemple fonctionne tu as besoin de la lib opensource :
Code xaml : 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 <Window x:Class="WpfAppSurfaceCS.ParametricSurfaceTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ParametricSurfaceTest" Height="300" Width="300"> <Grid> <Viewport3D Name="viewport"> <Viewport3D.Camera> <PerspectiveCamera Position="3,3,2" LookDirection="-3,-3,-2" UpDirection="0,1,0"/> </Viewport3D.Camera> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <AmbientLight Color="White"/> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D> </Grid> </Window>
3DTools pour WPF sur le site Miicrosoft CodePlex.
Cette lib comporte meme un control TrackBall pour deplacer toute la scene en 3D (semblable au Gyroscope d'Autocad).
Petit detail dans les 2 exemples:si AmbientLight=White on voit seulement le maillage .
Mets AmbientLight=Blue ou tout autre LinearGradientBrush pour avoir un apercu saissant.
Lien CodePlex pour la lib 3DTools de Microsoft Team:
http://www.google.fr/url?sa=t&source...8pxGTh9_hK2hKw
En esperant que cela aide............
bon code...............
Rebonjour Gualino
Fais gaffe dans l'exemple donne au systeme de coords.
Rappelle -toi qu'en GDI a cause de la frappe du texte les "english" de Microsoft ont oriente l'axe Y vers le bas ce qui se justifie aisement (et pan pour les malheureux graphistes que nous sommes ).
Mais la nouveaute dans WPF -quand on fait uniquement de la 3D-est que l'axe Y est "up" c.à.d oriente vers le haut et l'axe Z vers le spectateur ecran de la scene.
Tant et si bien que dans notre exemple pour dessiner une surface mathemat.
z=f(x,y) l'auteur du code a tout programme en inversant les roles des variables y et z soit :
- notre z => Y WPF
- notre y => Z WPF.
de maniere que la surface se "dresse" normalement" à l'ecran comme on le voit dans ce bout de code de SimpleSurface:
Alors croise dans la tete y et z à chaque fois.
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 //carroyage x,y de la grille ou nz joue le role de notre y dans la classe Simple Surface private int nx = 30; private int nz = 30; //ou bien encore ici: for (int j = 0; j < Nz; j++) { double z = Zmin + j * dz; pts[i, j] = f(x, z); // c'est F(x,y) //Formule de la courbe Sinc dans WinSimpleSurfaceTest private Point3D Sinc(double x, double z) { double r = Math.Sqrt(x * x + z * z) + 0.00001; //ce z est notre y double y = Math.Sin(r) / r;// return new Point3D(x, y, z); }
Il en est de meme pour u et v dans la surface parametre ou u est le parametre pour notre x et v pour notre y qui un est un z de WPF.......
bon code........
Partager