VectorVisualizer Version 1.2
by Kevin Seib and Pascal Glaeser
Loading...
Searching...
No Matches
Form1.cs
Go to the documentation of this file.
1using NCalc;
2using System;
3using System.Drawing;
4using System.Globalization;
5using System.Text.RegularExpressions;
6using System.Windows.Forms;
8
10{
11 public partial class Form1 : Form
12 {
13 private Button btnSkalarfeld;
14 private Button btnVektorfeld;
15 private CheckBox cbIs3D;
16
17 public Form1()
18 {
19 InitializeComponent();
20 InitializeStartScreen();
21 }
22
23 private void InitializeStartScreen()
24 {
25 this.Controls.Clear();
26 this.BackColor = Color.FromArgb(33, 33, 33);
27 this.ForeColor = Color.White;
28 this.Text = "Vektorkalkül Visualisierung";
29 this.Size = new Size(600, 400);
30
31 btnSkalarfeld = new Button();
32 btnSkalarfeld.Text = "Skalarfeld";
33 btnSkalarfeld.Size = new Size(120, 40);
34 btnSkalarfeld.Location = new Point(100, 100);
35 btnSkalarfeld.Click += BtnSkalarfeld_Click;
36 this.Controls.Add(btnSkalarfeld);
37
38 btnVektorfeld = new Button();
39 btnVektorfeld.Text = "Vektorfeld";
40 btnVektorfeld.Size = new Size(120, 40);
41 btnVektorfeld.Location = new Point(100, 160);
42 btnVektorfeld.Click += BtnVektorfeld_Click;
43 this.Controls.Add(btnVektorfeld);
44
45 cbIs3D = new CheckBox();
46 cbIs3D.Text = "Ist die Funktion 3D?";
47 cbIs3D.ForeColor = Color.White;
48 cbIs3D.BackColor = Color.FromArgb(33, 33, 33);
49 cbIs3D.Location = new Point(250, 130);
50 cbIs3D.AutoSize = true;
51 this.Controls.Add(cbIs3D);
52 }
53 private string NormalizeExpression(string expr)
54 {
55 // einfache Variablen: x^2 → Pow(x,2)
56 expr = Regex.Replace(expr, @"(\b[a-zA-Z_]\w*)\^(\d+)", "Pow($1,$2)");
57 // Klammerausdrücke: (x+1)^2 → Pow((x+1),2)
58 expr = Regex.Replace(expr, @"\‍(([^()]+)\‍)\^(\d+)", "Pow(($1),$2)");
59 return expr;
60 }
61
62
63 private void BtnSkalarfeld_Click(object sender, EventArgs e)
64 {
65 {
66 }
67 bool is3D = cbIs3D.Checked;
68
69 this.Controls.Clear();
70 this.BackColor = Color.FromArgb(33, 33, 33);
71 this.ForeColor = Color.White;
72
73 Label lblFunc = new Label();
74 lblFunc.Text = is3D ? "Skalarfeld f(x, y, z):" : "Skalarfeld f(x, y):";
75 lblFunc.Location = new Point(30, 30);
76 lblFunc.AutoSize = true;
77 this.Controls.Add(lblFunc);
78
79 TextBox txtFunc = new TextBox();
80 txtFunc.Location = new Point(170, 25);
81 txtFunc.Width = 300;
82 this.Controls.Add(txtFunc);
83
84 Label lblPoint = new Label();
85 lblPoint.Text = is3D ? "Punkt (x, y, z):" : "Punkt (x, y):";
86 lblPoint.Location = new Point(30, 70);
87 lblPoint.AutoSize = true;
88 this.Controls.Add(lblPoint);
89
90 TextBox txtX = new TextBox();
91 txtX.Location = new Point(170, 65);
92 txtX.Width = 60;
93 this.Controls.Add(txtX);
94
95 TextBox txtY = new TextBox();
96 txtY.Location = new Point(240, 65);
97 txtY.Width = 60;
98 this.Controls.Add(txtY);
99
100 TextBox txtZ = null;
101 if (is3D)
102 {
103 txtZ = new TextBox();
104 txtZ.Location = new Point(310, 65);
105 txtZ.Width = 60;
106 this.Controls.Add(txtZ);
107 }
108
109 CheckBox cbGradient = new CheckBox();
110 cbGradient.Text = "Gradient anzeigen (Falls valide Punkte gegeben sind)";
111 cbGradient.ForeColor = Color.White;
112 cbGradient.BackColor = Color.FromArgb(33, 33, 33);
113 cbGradient.Location = new Point(30, 110);
114 cbGradient.AutoSize = true;
115 this.Controls.Add(cbGradient);
116 Button btnVisualisieren = new Button();
117 btnVisualisieren.Text = "Visualisieren";
118 btnVisualisieren.Location = new Point(30, 140);
119 btnVisualisieren.Size = new Size(120, 30);
120 btnVisualisieren.Click += (s, args) =>
121
122 {
123 try
124 {
125 string expr = txtFunc.Text.Trim();
126 if (string.IsNullOrWhiteSpace(expr))
127 {
128 MessageBox.Show("Bitte eine Funktion eingeben.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
129 return;
130 }
131
132 // Vorab prüfen, ob Ausdruck gültig ist
133 try
134 {
135 expr = NormalizeExpression(expr);
136 var testExpr = new Expression(expr);
137
138 testExpr.Parameters["x"] = 1.0;
139 testExpr.Parameters["y"] = 1.0;
140 if (is3D)
141 testExpr.Parameters["z"] = 1.0;
142
143 var result = testExpr.Evaluate();
144 if (result == null || double.IsNaN(Convert.ToDouble(result)))
145 throw new Exception("Ergebnis ist ungültig");
146 }
147 catch (Exception ex)
148 {
149 MessageBox.Show("Die Funktion ist ungültig oder nicht auswertbar.\nDetails: " + ex.Message,
150 "Parserfehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
151 return;
152 }
153
154
155 double? px = null, py = null, pz = null;
156 double xVal = 0, yVal = 0;
157 bool hasX = !string.IsNullOrWhiteSpace(txtX.Text);
158 bool hasY = !string.IsNullOrWhiteSpace(txtY.Text);
159
160 if ((hasX && !hasY) || (!hasX && hasY))
161 {
162 MessageBox.Show("Bitte entweder beide Koordinaten x und y angeben oder keine.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
163 return;
164 }
165
166 if (hasX && !double.TryParse(txtX.Text, out xVal))
167 {
168 MessageBox.Show("x ist keine gültige Zahl.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
169 return;
170 }
171
172 if (hasY && !double.TryParse(txtY.Text, out yVal))
173 {
174 MessageBox.Show("y ist keine gültige Zahl.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
175 return;
176 }
177
178 if (hasX) px = xVal;
179 if (hasY) py = yVal;
180
181 if (is3D && txtZ != null && !string.IsNullOrWhiteSpace(txtZ.Text))
182 {
183 if (!double.TryParse(txtZ.Text, out double zVal))
184 {
185 MessageBox.Show("z ist keine gültige Zahl.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
186 return;
187 }
188 pz = zVal;
189 }
190
191 if (!is3D)
192 {
193 int size = 50;
194 double xMin = -5, xMax = 5;
195 double yMin = -5, yMax = 5;
196 double stepX = (xMax - xMin) / size;
197 double stepY = (yMax - yMin) / size;
198
199 double[,] values = new double[size, size];
200
201 for (int i = 0; i < size; i++) // i = x, j = y
202 {
203 for (int j = 0; j < size; j++)
204 {
205 double x = xMin + i * stepX;
206 double y = yMin + j * stepY;
207 try
208 {
209 values[size - j - 1,i] = EvaluateScalarField(expr, x, y);
210 }
211 catch
212 {
213 values[size - j - 1,i] = double.NaN;
214 }
215 }
216 }
217
218 string? gradientText = null;
219 if (cbGradient.Checked && px.HasValue && py.HasValue)
220 {
221 Func<double, double, double> funcDelegate = (x, y) => EvaluateScalarField(expr, x, y);
222 var grad = FieldOperations.ComputeGradient2D(funcDelegate, px.Value, py.Value);
223 gradientText = $"(∂f/∂x, ∂f/∂y): \n ({Math.Round(grad[0], 4)}, {Math.Round(grad[1], 4)})";
224 }
225
226 var plotWindow = new PlotForm(values, xMin, xMax, yMin, yMax, gradientText, cbGradient.Checked);
227 plotWindow.StartPosition = FormStartPosition.CenterScreen;
228 plotWindow.Show();
229
230 }
231 else
232 {
233 // Ausdruck validieren
234 expr = NormalizeExpression(expr);
235 var testExpr = new Expression(expr);
236 testExpr.Parameters["x"] = 1.0;
237 testExpr.Parameters["y"] = 1.0;
238 testExpr.Parameters["z"] = 1.0;
239 try
240 {
241 testExpr.Evaluate();
242 }
243 catch
244 {
245 MessageBox.Show("Funktion ungültig.", "Fehler");
246 return;
247 }
248 Func<double, double, double, double> func3D = (x, y, z) =>
249 EvaluateScalarField(expr, x, y, z);
250
251 // Punkt einlesen (optional)
252 double? ppx = null, ppy = null, ppz = null;
253
254 bool hasZ = !string.IsNullOrWhiteSpace(txtZ.Text);
255
256 // Fehler, wenn nur teilweise befüllt
257 if ((hasX || hasY || hasZ) && !(hasX && hasY && hasZ))
258 {
259 MessageBox.Show("Bitte entweder alle drei Koordinaten (x, y, z) angeben oder keine.",
260 "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
261 return;
262 }
263
264 // Falls alle drei gesetzt sind, versuche sie zu parsen
265 if (hasX && hasY && hasZ)
266 {
267 if (
268 double.TryParse(txtX.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out xVal) &&
269 double.TryParse(txtY.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out yVal) &&
270 double.TryParse(txtZ.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out double zVal))
271 {
272 ppx = xVal;
273 ppy = yVal;
274 ppz = zVal;
275 }
276 else
277 {
278 MessageBox.Show("Bitte gültige Zahlen für x, y und z eingeben.",
279 "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
280 return;
281 }
282 }
283
284
285 // Gradienten berechnen (falls gewünscht)
286 double zFixed = ppz ?? 0; // Ebene, auf der geplottet wird
287 string? gradientText = null;
288
289 if (cbGradient.Checked && ppx.HasValue && ppy.HasValue && ppz.HasValue)
290 {
291 var grad = FieldOperations.ComputeGradient3D(func3D, ppx.Value, ppy.Value, ppz.Value);
292 gradientText =
293 $"(∂f/∂x, ∂f/∂y, ∂f/∂z): \n " +
294 $"({Math.Round(grad[0], 4)}, {Math.Round(grad[1], 4)}, {Math.Round(grad[2], 4)})";
295 }
296
297 // Visualisierung starten
298 var plotWindow = new PlotForm3D(func3D, zFixed, 80, gradientText);
299 plotWindow.StartPosition = FormStartPosition.CenterScreen;
300 plotWindow.Show();
301 }
302
303
304
305
306
307 }
308 catch (Exception ex)
309 {
310 MessageBox.Show("Fehler bei der Berechnung:\n" + ex.Message,
311 "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
312 }
313 };
314 this.Controls.Add(btnVisualisieren);
315 this.Controls.Add(CreateBackButton());
316
317 }
318
319 private void BtnVektorfeld_Click(object sender, EventArgs e)
320 {
321 bool is3D = cbIs3D.Checked;
322
323 this.Controls.Clear();
324 this.BackColor = Color.FromArgb(33, 33, 33);
325 this.ForeColor = Color.White;
326
327 if (!is3D)
328 {
329 Label lblFx = new Label { Text = "Fx(x, y):", Location = new Point(30, 30), AutoSize = true };
330 TextBox txtFx = new TextBox { Location = new Point(100, 25), Width = 300 };
331 this.Controls.Add(lblFx);
332 this.Controls.Add(txtFx);
333
334 Label lblFy = new Label { Text = "Fy(x, y):", Location = new Point(30, 70), AutoSize = true };
335 TextBox txtFy = new TextBox { Location = new Point(100, 65), Width = 300 };
336 this.Controls.Add(lblFy);
337 this.Controls.Add(txtFy);
338
339 Label lblPoint = new Label { Text = "Punkt (x, y):", Location = new Point(30, 110), AutoSize = true };
340 TextBox txtX = new TextBox { Location = new Point(130, 105), Width = 60 };
341 TextBox txtY = new TextBox { Location = new Point(200, 105), Width = 60 };
342 this.Controls.Add(lblPoint);
343 this.Controls.Add(txtX);
344 this.Controls.Add(txtY);
345
346 CheckBox cbDivergenz = new CheckBox { Text = "Divergenz anzeigen", Location = new Point(30, 150), AutoSize = true, ForeColor = Color.White, BackColor = Color.FromArgb(33, 33, 33) };
347 CheckBox cbRotation = new CheckBox { Text = "Rotation anzeigen", Location = new Point(30, 180), AutoSize = true, ForeColor = Color.White, BackColor = Color.FromArgb(33, 33, 33) };
348 this.Controls.Add(cbDivergenz);
349 this.Controls.Add(cbRotation);
350
351 Button btnVisualisieren = new Button { Text = "Visualisieren", Location = new Point(30, 220), AutoSize = true, BackColor = Color.FromArgb(33, 33, 33), ForeColor = Color.White };
352 btnVisualisieren.Size = new Size(120, 30);
353 this.Controls.Add(btnVisualisieren);
354 this.Controls.Add(CreateBackButton());
355
356 btnVisualisieren.Click += (s, args) =>
357 {
358 try
359 {
360 string fxExpr = NormalizeExpression(txtFx.Text.Trim());
361 string fyExpr = NormalizeExpression(txtFy.Text.Trim());
362
363 if (string.IsNullOrWhiteSpace(fxExpr) || string.IsNullOrWhiteSpace(fyExpr))
364 {
365 MessageBox.Show("Bitte sowohl Fx als auch Fy eingeben.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
366 return;
367 }
368
369 try
370 {
371 var testFx = new Expression(fxExpr);
372 var testFy = new Expression(fyExpr);
373 testFx.Parameters["x"] = 1.0;
374 testFx.Parameters["y"] = 1.0;
375 testFy.Parameters["x"] = 1.0;
376 testFy.Parameters["y"] = 1.0;
377 testFx.Evaluate();
378 testFy.Evaluate();
379 }
380 catch
381 {
382 MessageBox.Show("Mindestens ein Ausdruck ist ungültig.", "Parserfehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
383 return;
384 }
385
386 double? px = null, py = null;
387 bool hasX = !string.IsNullOrWhiteSpace(txtX.Text);
388 bool hasY = !string.IsNullOrWhiteSpace(txtY.Text);
389
390 if ((hasX && !hasY) || (!hasX && hasY))
391 {
392 MessageBox.Show("Bitte entweder beide Koordinaten x und y angeben oder keine.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
393 return;
394 }
395
396 double xVal = 0, yVal = 0;
397 if (hasX && !double.TryParse(txtX.Text, out xVal))
398 {
399 MessageBox.Show("x ist keine gültige Zahl.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
400 return;
401 }
402 if (hasY && !double.TryParse(txtY.Text, out yVal))
403 {
404 MessageBox.Show("y ist keine gültige Zahl.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
405 return;
406 }
407
408 if (hasX && hasY)
409 {
410 px = xVal;
411 py = yVal;
412 }
413
414 int size = 25;
415 double xMin = -5, xMax = 5;
416 double yMin = -5, yMax = 5;
417 double stepX = (xMax - xMin) / size;
418 double stepY = (yMax - yMin) / size;
419
420 double[][,] vectorField = new double[2][,];
421 vectorField[0] = new double[size, size];
422 vectorField[1] = new double[size, size];
423
424 double[,] divergence = null;
425 double[,] rotation = null;
426
427 Func<double, double, double[]> vectorFunc = (x, y) =>
428 {
429 double fx = EvaluateScalarField(fxExpr, x, y);
430 double fy = EvaluateScalarField(fyExpr, x, y);
431 return new double[] { fx, fy };
432 };
433
434 if (cbDivergenz.Checked) divergence = new double[size, size];
435 if (cbRotation.Checked) rotation = new double[size, size];
436
437 for (int i = 0; i < size; i++)
438 {
439 for (int j = 0; j < size; j++)
440 {
441 double x = xMin + i * stepX;
442 double y = yMin + j * stepY;
443 try
444 {
445 var vec = vectorFunc(x, y);
446 vectorField[0][i, j] = vec[0];
447 vectorField[1][i, j] = vec[1];
448
449 if (cbDivergenz.Checked)
450 divergence[i, j] = FieldOperations.ComputeDivergence2D(vectorFunc, x, y);
451 if (cbRotation.Checked)
452 rotation[i, j] = FieldOperations.ComputeCurl2D(vectorFunc, x, y);
453 }
454 catch
455 {
456 vectorField[0][i, j] = double.NaN;
457 vectorField[1][i, j] = double.NaN;
458 if (divergence != null) divergence[i, j] = double.NaN;
459 if (rotation != null) rotation[i, j] = double.NaN;
460 }
461 }
462 }
463
464 var plotWindow = new VektorPlotForm2D(vectorField, xMin, xMax, yMin, yMax, divergence, rotation, px, py);
465 plotWindow.StartPosition = FormStartPosition.CenterScreen;
466 plotWindow.Show();
467 }
468 catch (Exception ex)
469 {
470 MessageBox.Show("Fehler bei der Berechnung:\n" + ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
471 }
472 };
473 }
474 else
475 {
476 InitializeVektorfeld3DGUI();
477 }
478 }
479 private void InitializeVektorfeld3DGUI()
480 {
481 this.Controls.Clear();
482 this.BackColor = Color.FromArgb(33, 33, 33);
483 this.ForeColor = Color.White;
484
485 // Fx(x,y,z)
486 Label lblFx = new Label { Text = "Fx(x, y, z):", Location = new Point(30, 30), AutoSize = true };
487 TextBox txtFx = new TextBox { Name = "txtFx3D", Location = new Point(130, 25), Width = 300 };
488 this.Controls.Add(lblFx);
489 this.Controls.Add(txtFx);
490
491 // Fy(x,y,z)
492 Label lblFy = new Label { Text = "Fy(x, y, z):", Location = new Point(30, 70), AutoSize = true };
493 TextBox txtFy = new TextBox { Name = "txtFy3D", Location = new Point(130, 65), Width = 300 };
494 this.Controls.Add(lblFy);
495 this.Controls.Add(txtFy);
496
497 // Fz(x,y,z)
498 Label lblFz = new Label { Text = "Fz(x, y, z):", Location = new Point(30, 110), AutoSize = true };
499 TextBox txtFz = new TextBox { Name = "txtFz3D", Location = new Point(130, 105), Width = 300 };
500 this.Controls.Add(lblFz);
501 this.Controls.Add(txtFz);
502
503 // Punkt (x,y,z)
504 Label lblPoint = new Label { Text = "Punkt (x, y, z):", Location = new Point(30, 150), AutoSize = true };
505 TextBox txtX = new TextBox { Name = "txtX3D", Location = new Point(130, 145), Width = 60 };
506 TextBox txtY = new TextBox { Name = "txtY3D", Location = new Point(200, 145), Width = 60 };
507 TextBox txtZ = new TextBox { Name = "txtZ3D", Location = new Point(270, 145), Width = 60 };
508 this.Controls.Add(lblPoint);
509 this.Controls.Add(txtX);
510 this.Controls.Add(txtY);
511 this.Controls.Add(txtZ);
512
513 // Checkbox Divergenz
514 CheckBox cbDivergenz = new CheckBox
515 {
516 Text = "Divergenz anzeigen",
517 Name = "cbDivergenz3D",
518 Location = new Point(30, 190),
519 AutoSize = true,
520 ForeColor = Color.White,
521 BackColor = Color.FromArgb(33, 33, 33)
522 };
523 this.Controls.Add(cbDivergenz);
524
525 // Checkbox Rotation
526 CheckBox cbRotation = new CheckBox
527 {
528 Text = "Rotation anzeigen",
529 Name = "cbRotation3D",
530 Location = new Point(30, 220),
531 AutoSize = true,
532 ForeColor = Color.White,
533 BackColor = Color.FromArgb(33, 33, 33)
534 };
535 this.Controls.Add(cbRotation);
536
537 // Button
538 Button btnVisualisieren = new Button
539 {
540 Text = "Visualisieren",
541 Location = new Point(30, 260),
542 Size = new Size(120, 30),
543 BackColor = Color.FromArgb(33, 33, 33),
544 ForeColor = Color.White
545 };
546 this.Controls.Add(btnVisualisieren);
547 this.Controls.Add(CreateBackButton());
548
549 btnVisualisieren.Click += (s, e) =>
550 {
551 try
552 {
553 // Controls holen
554 string fxExpr = NormalizeExpression(((TextBox)this.Controls["txtFx3D"]).Text.Trim());
555 string fyExpr = NormalizeExpression(((TextBox)this.Controls["txtFy3D"]).Text.Trim());
556 string fzExpr = NormalizeExpression(((TextBox)this.Controls["txtFz3D"]).Text.Trim());
557
558 string xText = ((TextBox)this.Controls["txtX3D"]).Text.Trim();
559 string yText = ((TextBox)this.Controls["txtY3D"]).Text.Trim();
560 string zText = ((TextBox)this.Controls["txtZ3D"]).Text.Trim();
561
562 bool hasX = !string.IsNullOrWhiteSpace(xText);
563 bool hasY = !string.IsNullOrWhiteSpace(yText);
564 bool hasZ = !string.IsNullOrWhiteSpace(zText);
565
566 bool showDiv = ((CheckBox)this.Controls["cbDivergenz3D"]).Checked;
567 bool showRot = ((CheckBox)this.Controls["cbRotation3D"]).Checked;
568
569 // Prüfung: leere oder alle 3 Koordinaten
570 if ((hasX || hasY || hasZ) && !(hasX && hasY && hasZ))
571 {
572 MessageBox.Show("Bitte entweder alle drei Koordinaten x, y, z angeben oder keine.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
573 return;
574 }
575
576 // Ausdruck prüfen
577 try
578 {
579 var t1 = new Expression(fxExpr);
580 var t2 = new Expression(fyExpr);
581 var t3 = new Expression(fzExpr);
582 t1.Parameters["x"] = 1.0;
583 t1.Parameters["y"] = 1.0;
584 t1.Parameters["z"] = 1.0;
585 t2.Parameters["x"] = 1.0;
586 t2.Parameters["y"] = 1.0;
587 t2.Parameters["z"] = 1.0;
588 t3.Parameters["x"] = 1.0;
589 t3.Parameters["y"] = 1.0;
590 t3.Parameters["z"] = 1.0;
591 t1.Evaluate(); t2.Evaluate(); t3.Evaluate();
592 }
593 catch
594 {
595 MessageBox.Show("Mindestens ein Ausdruck ist ungültig.", "Parserfehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
596 return;
597 }
598
599 // Punkt optional einlesen
600 double? px = null, py = null, pz = null;
601 if (hasX && hasY && hasZ)
602 {
603 if (double.TryParse(xText, NumberStyles.Float, CultureInfo.InvariantCulture, out double xVal) &&
604 double.TryParse(yText, NumberStyles.Float, CultureInfo.InvariantCulture, out double yVal) &&
605 double.TryParse(zText, NumberStyles.Float, CultureInfo.InvariantCulture, out double zVal))
606 {
607 px = xVal; py = yVal; pz = zVal;
608 }
609 else
610 {
611 MessageBox.Show("Bitte gültige Werte für x, y, z eingeben.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
612 return;
613 }
614 }
615
616 // Vektorfeldfunktion
617 Func<double, double, double, double[]> vectorFunc = (x, y, z) =>
618 {
619 return new double[]
620 {
621 EvaluateScalarField(fxExpr, x, y, z),
622 EvaluateScalarField(fyExpr, x, y, z),
623 EvaluateScalarField(fzExpr, x, y, z)
624 };
625 };
626
627 // Feld berechnen
628 int size = 10;
629 double min = -5, max = 5;
630 double step = (max - min) / size;
631
632 var vectors = new double[3][,,];
633 vectors[0] = new double[size, size, size]; // Fx
634 vectors[1] = new double[size, size, size]; // Fy
635 vectors[2] = new double[size, size, size]; // Fz
636
637 double[,,] divergence = showDiv ? new double[size, size, size] : null;
638 double[][,,] curl = showRot ? new double[3][,,] : null;
639 if (showRot)
640 {
641 curl[0] = new double[size, size, size]; // curl_x
642 curl[1] = new double[size, size, size]; // curl_y
643 curl[2] = new double[size, size, size]; // curl_z
644 }
645
646 for (int i = 0; i < size; i++)
647 {
648 for (int j = 0; j < size; j++)
649 {
650 for (int k = 0; k < size; k++)
651 {
652 double x = min + i * step;
653 double y = min + j * step;
654 double z = min + k * step;
655 try
656 {
657 var vec = vectorFunc(x, y, z);
658 vectors[0][i, j, k] = vec[0];
659 vectors[1][i, j, k] = vec[1];
660 vectors[2][i, j, k] = vec[2];
661
662 if (showDiv)
663 divergence[i, j, k] = FieldOperations.ComputeDivergence3D(vectorFunc, x, y, z);
664
665 if (showRot)
666 {
667 var rot = FieldOperations.ComputeCurl3D(vectorFunc, x, y, z);
668 curl[0][i, j, k] = rot[0];
669 curl[1][i, j, k] = rot[1];
670 curl[2][i, j, k] = rot[2];
671 }
672 }
673 catch
674 {
675 vectors[0][i, j, k] = vectors[1][i, j, k] = vectors[2][i, j, k] = double.NaN;
676 if (showDiv) divergence[i, j, k] = double.NaN;
677 if (showRot) { curl[0][i, j, k] = curl[1][i, j, k] = curl[2][i, j, k] = double.NaN; }
678 }
679 }
680 }
681 }
682
683 // Entscheide, ob das InfoPanel angezeigt werden soll
684 bool showInfoPanel = (showDiv || showRot) && px.HasValue && py.HasValue && pz.HasValue;
685
686 var plotWindow = new VektorPlotForm3D(
687 vectors,
688 -5, 5, -5, 5, -5, 5,
689 showInfoPanel ? divergence : null,
690 showInfoPanel ? curl : null,
691 px, py, pz);
692
693 plotWindow.StartPosition = FormStartPosition.CenterScreen;
694 plotWindow.Show();
695
696
697 }
698 catch (Exception ex)
699 {
700 MessageBox.Show("Fehler:\n" + ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
701 }
702 };
703
704 }
705
706
707
708
709 private double EvaluateScalarField(string expressionText, double x, double y, double? z = null)
710 {
711 var expr = new Expression(expressionText);
712 expr.Parameters["x"] = x;
713 expr.Parameters["y"] = y;
714 if (z.HasValue)
715 expr.Parameters["z"] = z.Value;
716
717 var result = expr.Evaluate();
718 return Convert.ToDouble(result);
719 }
720 private double Evaluate(Expression expr, double x, double y)
721 {
722 expr.Parameters["x"] = x;
723 expr.Parameters["y"] = y;
724 return Convert.ToDouble(expr.Evaluate());
725 }
726
727 private Button CreateBackButton()
728 {
729 Button btnBack = new Button();
730 btnBack.Text = "Zurück";
731 btnBack.Size = new Size(100, 30);
732 btnBack.BackColor = Color.FromArgb(55, 55, 55);
733 btnBack.ForeColor = Color.White;
734 btnBack.Location = new Point(this.ClientSize.Width - 120, this.ClientSize.Height - 50);
735 btnBack.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
736 btnBack.Click += (s, e) => InitializeStartScreen();
737 return btnBack;
738 }
739
740 private void Form1_Load(object sender, EventArgs e)
741 {
742
743 }
744 }
745}