using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; namespace Funktionsplotter { public partial class Form1 : Form { private Bitmap bmp; private Pen blackPen, redPen, greenPen, violetPen; private PointF[] point_a = new PointF[2000]; private PointF[] point_b = new PointF[2000]; private PointF[] point_c = new PointF[2000]; private PointF[] point_d = new PointF[2000]; // Punktearrays für die Funktion und die Ableitungen private int counter_ableitungen = 0, count_saver = 0; // Counter um Ausgabe-Ableitung zu steuern private string func_a, func_b, func_c, func_d; // Die Funktionen werden hier gespeichert public Form1() { InitializeComponent(); textBox3.Enabled = false; textBox6.Enabled = false; textBox7.Enabled = false; init_pic(); // Achsenkreuz wird erstellt } private void button2_Click(object sender, EventArgs e) // Grafik wird auf dem Desktop gesichert { string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); count_saver++; pictureBox1.Image.Save(path + "/bitmap_grafik_" + count_saver + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp); } private void button1_Click(object sender, EventArgs e) { // Formt Eingabe zur Normalform um textBox3.Clear(); textBox6.Clear(); textBox7.Clear(); listBox2.Items.Clear(); init_pic(); counter_ableitungen = 0; // Counter um die Ausgabe nach Ableitungen zu leiten if (richTextBox1.Text != "" && textBox1.Text != "" && textBox2.Text != "" && Convert.ToDouble(textBox1.Text) > Convert.ToDouble(textBox2.Text)) { // Überprüft Eingabe auf Richtigkeit string str = richTextBox1.Text; if (str[0] != '+' && str[0] != '-') str = '+' + str; // Wenn kein Rechenzeichen am Beginn des Strings steht, wird eins hinzugefügt for (int i = 0; i < str.Length; i++) // Überprüft ob ein einzelnes X in der Funktion ist und setzt ein ^1 ein { if (str[i] == 'x' && str[i + 1] != '²' && str[i + 1] != '³') { str = str.Insert(i + 1, "¹"); } } if (!str.Contains('³')) // Wenn kein x³ vorhanden wird eines eingefügt { str = str.Insert(0, "0x³"); } if (str.Contains('³') && !str.Contains('²')) // Wenn kein x² vorhanden, so wird eines an der passenden Stelle eingefügt { for (int i = 0; i < str.Length; i++) { if (str[i] == 'x' && str[i + 1] == '³') str = str.Insert(i + 2, "+0x²"); } } if (str.Contains('²') && !str.Contains('¹')) // Wenn kein x^1 vorhanden ist wird eines eingefügt { for (int i = 0; i < str.Length; i++) { if (str[i] == 'x' && str[i + 1] == '²') str = str.Insert(i + 2, "+0x¹"); } } for (int i = 0; i < str.Length; i++) // Setzt ein 'd' ein wenn nicht vorhanden { if (str[i] == '¹') { if ((i + 1) >= str.Length) { str = str.Insert(i + 1, "+0"); } } } string new_string_two = str; int new_count_two = 0; for (int i = 0; i < str.Length; i++) // Wenn x alleine steht wird eine 1 hinzugefügt { if (str[i] == 'x') { if (!Char.IsDigit((str[i - 1]))) { new_string_two = new_string_two.Insert(i - new_count_two, "1"); new_count_two++; } } } str = new_string_two; string new_string = str; int new_count = 0; for (int i = 0; i < str.Length; i++) // Setzt vor ein x ein * { if (str[i] == 'x') { new_string = new_string.Insert(i + new_count, "*"); new_count++; } } str = new_string; func_a = str; // Original Funktion wird in func_a gesichert calc_ableitung(str); // Zur Ableitungsfunktion draw_stuff(); // Nach den Ableitungen wird der Zeichnenmethode übergeben } else { MessageBox.Show("Bitte geben Sie eine gültige Funktion 3. Grades und gültige Grenzen ein!"); } } private void draw_stuff() // Zeichnet meine Funktionen { bool calc_b_check = false, calc_c_check = false, calc_d_check = false; for (int i = 0; i < func_b.Length; i++) { // Überprüft ob Funktion Zeichenbar ist. (a, b, c oder d nicht null) if (Char.IsDigit(func_b[i])) { if (func_b[i] != '0') calc_b_check = true; } } for (int i = 0; i < func_c.Length; i++) { // Überprüft ob Funktion Zeichenbar ist. (a, b, c oder d nicht null) if (Char.IsDigit(func_c[i])) { if (func_c[i] != '0') calc_c_check = true; } } for (int i = 0; i < func_d.Length; i++) { // Überprüft ob Funktion Zeichenbar ist. (a, b, c oder d nicht null) if (Char.IsDigit(func_d[i])) { if (func_d[i] != '0') calc_d_check = true; } } for (int i = -1000; i < 1000; i++)// Rechnet das Punktearray der Originalfunktion { string question = func_a.Replace("x", "(" + i.ToString() + ")"); float py = Convert.ToSingle(rechne_funktion(question)), px = i; if (i < 0) py = py * -1; // Der Workaround von dem unten geredet wird. (Bei der Rechnenfunktion) if (i >= Convert.ToInt32(textBox2.Text) && i <= Convert.ToInt32(textBox1.Text)) { listBox2.Items.Add("y= " + py + ", x= " + px); } point_a[i + 1000] = new PointF(px, py); } if (calc_b_check) // Überprüft ob Rechnen sinnvoll ist { listBox2.Items.Add("Ableitung 1: \n"); for (int i = -1000; i < 1000; i++)// Rechnet das Punktearray der ersten Ableitung { string question = func_b.Replace("x", "(" + i.ToString() + ")"); float py = Convert.ToSingle(rechne_funktion(question)), px = i; if (i < 0) py = py * -1; // Der Workaround von dem unten geredet wird. (Bei der Rechnenfunktion) if (i >= Convert.ToInt32(textBox2.Text) && i <= Convert.ToInt32(textBox1.Text)) { listBox2.Items.Add("y= " + py + ", x= " + px); } point_b[i + 1000] = new PointF(px, py); } } if (calc_c_check) // Überprüft ob Rechnen sinnvoll ist { listBox2.Items.Add("Ableitung 2: \n"); for (int i = -1000; i < 1000; i++)// Rechnet das Punktearray der zeiten Ableitung { string question = func_c.Replace("x", "(" + i.ToString() + ")"); float py = Convert.ToSingle(rechne_funktion(question)), px = i; if (i < 0) py = py * -1; // Der Workaround von dem unten geredet wird. (Bei der Rechnenfunktion) if (i >= Convert.ToInt32(textBox2.Text) && i <= Convert.ToInt32(textBox1.Text)) { listBox2.Items.Add("y= " + py + ", x= " + px); } point_c[i + 1000] = new PointF(px, py); } } if (calc_d_check) // Überprüft ob das Zeichnen sinnvoll ist { listBox2.Items.Add("Ableitung 3: \n"); for (int i = -1000; i < 1000; i++)// Rechnet das Punktearray der dritten Ableitung { string question = func_d.Replace("x", "(" + i.ToString() + ")"); float py = Convert.ToSingle(rechne_funktion(question)), px = i; if (i < 0) py = py * -1; // Der Workaround von dem unten geredet wird. (Bei der Rechnenfunktion) if (i >= Convert.ToInt32(textBox2.Text) && i <= Convert.ToInt32(textBox1.Text)) { listBox2.Items.Add("y= " + py + ", x= " + px); } point_d[i + 1000] = new PointF(px, py); } } draw_my_field(); // Übergibt an die Zeichnenfunktion } private void calc_ableitung(string str) { // Berechnet Ableitungen char calc_sym_1 = str[0], calc_sym_2 = '+', calc_sym_3 = '+'; for (int i = 0; i < str.Length; i++) // Nimmt Rechenzeichen nach der Hochzahl { try // Fliegt aus dem Indexbereich wenn ³ z.B. nicht vorhanden ist. Führt zu keinen Problemen im übrigen Code. { if (str[i] == '³') calc_sym_2 = str[i + 1]; if (str[i] == '²') calc_sym_3 = str[i + 1]; }catch { } } string[] str_content = str.Split('+', '-'); int multiplikator = 0; string erg = ""; for (int i = 0; i < str_content.Length - 1; i++) // Geht der Länge des arrays nach durch die Splits um abzuleiten { for (int j = 0; j < str_content[i].Length ; j++) // Checkt jeden Part der Funktion nach Hochzeichen um ableiten zu können { string new_str_content = str_content[i]; if (new_str_content[j] == '³') { // Wenn im Part dieses Hochzeichen gefunden wurde so wird abgeleitet multiplikator = 3; string[] new_str_array = new_str_content.Split('*'); string ins = calc_sym_1 + new_str_array[0]; // Nimmt Rechenzeichen vor dem ^3 und verbindet es mit der Zahl vor dem * double varia = Convert.ToDouble(ins) * multiplikator; // Rechnet die neue Basis aus erg = erg + calc_sym_1 + varia.ToString() + "*x²"; // Fügt den neuen Exponenten an } if (new_str_content[j] == '²') { multiplikator = 2; string[] new_str_array = new_str_content.Split('*'); string ins = calc_sym_2 + new_str_array[0]; double varia = Convert.ToDouble(ins) * multiplikator; erg = erg + calc_sym_2 + varia.ToString() + "*x¹"; } if (new_str_content[j] == '¹') { multiplikator = 1; string[] new_str_array = new_str_content.Split('*'); string ins = calc_sym_3 + new_str_array[0]; double varia = Convert.ToDouble(ins) * multiplikator; erg = erg + calc_sym_3 + varia.ToString(); } } } if (erg.Contains('x')) calc_ableitung(erg); // Wenn noch Xe vorhanden sind, so wird die Ableitungsfunktion noch einmal aufgerufen counter_ableitungen++; if (erg != "" && counter_ableitungen == 1) { // Fügt 3te Ableitung ein textBox7.Text = erg; func_d = erg; } if (erg != "" && counter_ableitungen == 2) { // Fügt 2te Ableitung ein textBox6.Text = erg; func_c = erg; } if (erg != "" && counter_ableitungen == 3) { // Fügt 1te Ableitung ein textBox3.Text = erg; func_b = erg; } } private void draw_my_field() // Zeichnet meine Punktearrays { blackPen = new Pen(System.Drawing.Color.Black); redPen = new Pen(System.Drawing.Color.Red); greenPen = new Pen(System.Drawing.Color.Green); violetPen = new Pen(System.Drawing.Color.Violet); using (Graphics g = Graphics.FromImage(bmp)) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // Kantenglättung g.TranslateTransform(pictureBox1.Width / 2, pictureBox1.Height / 2); // Koordinatensystem Ursprung wird verlegt g.ScaleTransform(1, -0.25F); // Skalierung g.DrawLines(blackPen, point_a); // Originalfunktion g.DrawLines(redPen, point_b); // Erste Ableitung g.DrawLines(greenPen, point_c); // Zweite Ableitung g.DrawLines(violetPen, point_d); // Dritte Ableitung } pictureBox1.Image = bmp; // Bild wird eingefügt } private void init_pic() // Achsenkreuz wird erstellt { blackPen = new Pen(Color.Black, 3); // Create points that define line. Point point1y = new Point(pictureBox1.Width / 2, 0); Point point2y = new Point(pictureBox1.Width / 2, pictureBox1.Height); Point point1x = new Point(0, pictureBox1.Height / 2); Point point2x = new Point(pictureBox1.Width, pictureBox1.Height / 2); // Draw lines to screen. bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height); using (Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.White); g.DrawImage(bmp, 0, 0); // Zeichnet bmp weiß for (int x = -250; x <= 500; x += 25) { // Raster X Achse g.DrawLine(new Pen(Color.Green), x, -pictureBox1.Height, x, pictureBox1.Height); } for (int y = -250; y <= 500; y += 25) { // Raster Y Achse g.DrawLine(new Pen(Color.Red), -pictureBox1.Width, y, pictureBox1.Width, y); } g.DrawLine(blackPen, point1y, point2y); g.DrawLine(blackPen, point1x, point2x); // Achsenkreuz } pictureBox1.Image = bmp; } private double rechne_funktion(string str) { // BSP: 2*(3)²+1*(-2)¹-3 string[] calc_array = str.Split('³', '²', '¹'); bool calc_1_check = false, calc_2_check = false, calc_3_check = false; for (int i = 0; i < str.Length; i++) { // Checkt Funktion auf vorhandene Grade if (str[i] == '¹') calc_1_check = true; if (str[i] == '²') calc_2_check = true; if (str[i] == '³') calc_3_check = true; } int pow = 0; // Zahl zum hochnehmen int begin_index = 0, end_index = 0; for (int i = 0; i < calc_array.Length; i++) // Geht Array durch {// BSP: 2*(3)²+1*(-2)¹-3 for (int j = 0; j < calc_array[i].Length; j++) // Geht Teil i des Arrays durch { string new_array = calc_array[i]; if (new_array[j] == '(') { begin_index = j; } if (new_array[j] == ')') { // Checkt nach Klammern end_index = j; if (calc_1_check) { pow = 1; calc_1_check = false; } if (calc_2_check) { pow = 2; calc_2_check = false; } if (calc_3_check) { pow = 3; calc_3_check = false; } // Nimmt die höchste Hochzahl und setzt den Checkwert auf false um doppelte Hochrechnung zu verhindern double pow_power = Math.Pow(Convert.ToDouble(new_array.Substring(begin_index + 1, end_index - begin_index - 1)), pow); // Nimmt die Zahl in den Indexen und nimmt sie mit der gegebenen Hochzahl hoch new_array = new_array.Remove(begin_index, end_index - begin_index + 1).Insert(begin_index, pow_power.ToString()); // Entfernt die Klammern und die Hochzahl, während das Ergebnis eingefügt wird calc_array[i] = new_array; // Wird im Array gesichert } } } string ergebnis_final = ""; for (int i = 0; i < calc_array.Length; i++) { // Das Ergebnis wird in einem String zusammengefügt ergebnis_final = ergebnis_final + calc_array[i]; } // I'm could not bring this **** to work properly! I will just use a workaround. // BSP: 2 * -100 + 1 * -100 - 3 /*string[] mult_calc_array = i_will_hail_to_my_coffee_if_this_will_work.Split('*'); string a = "", b = ""; string mul_a = "", mul_b = "", mul_c = ""; for (int i = 0; i < mult_calc_array.Length - 1; i++) { int counter = 0, indexer = 0, counter_b = 0; for (int j = mult_calc_array[i].Length - 1; j >= 0; j--) { //MessageBox.Show("fy"); string lost_count_of_arrays_or_strings = mult_calc_array[i]; if (Char.IsDigit(lost_count_of_arrays_or_strings[j])) { counter++; indexer = j; } try { if (lost_count_of_arrays_or_strings[indexer - 1] == '-' || lost_count_of_arrays_or_strings[indexer - 1] == '+') { counter++; break; } } catch { } } int trying = (mult_calc_array[i].Length) - (counter ); a = mult_calc_array[i].Substring(trying, counter); for (int j = 0; j < mult_calc_array[i + 1].Length; j++) { string lost_count_of_arrays_or_strings = mult_calc_array[i + 1]; if (lost_count_of_arrays_or_strings[j] == '-' && j == 0) counter_b++; if (Char.IsDigit(lost_count_of_arrays_or_strings[j])) { counter_b++; } } b = mult_calc_array[i + 1].Substring(0, counter_b - 1); double c = Convert.ToDouble(a) * Convert.ToDouble(b); if (i == 0) mul_a = c.ToString(); if (i == 1) mul_b = c.ToString(); if (i == 2) mul_c = c.ToString(); } MessageBox.Show(mul_a + ", " + mul_b + ", " + mul_c); int count_for = 0, count_back = 0; for (int i = 0; i < i_will_hail_to_my_coffee_if_this_will_work.Length; i++) { if (i_will_hail_to_my_coffee_if_this_will_work[i] == '*') { for (int j = 0; j < i_will_hail_to_my_coffee_if_this_will_work.Length; j++) { if (Char.IsDigit(i_will_hail_to_my_coffee_if_this_will_work[i - j]) ) { count_back++; } if (Char.IsDigit(i_will_hail_to_my_coffee_if_this_will_work[i + j])) { count_for++; } } } } int index = i_will_hail_to_my_coffee_if_this_will_work.IndexOf('*'); int index_2 = i_will_hail_to_my_coffee_if_this_will_work.IndexOf('*', index); int index_3 = i_will_hail_to_my_coffee_if_this_will_work.IndexOf('*', index_2); int begin_a = 0, end_a = 0, begin_b = 0, end_b = 0, begin_c = 0, end_c = 0; if(index != -1) { for (int i = 0; i < i_will_hail_to_my_coffee_if_this_will_work.Length; i++) { if (Char.IsDigit(i_will_hail_to_my_coffee_if_this_will_work[index - i])) begin_a++; if (Char.IsDigit(i_will_hail_to_my_coffee_if_this_will_work[index + i]) && i_will_hail_to_my_coffee_if_this_will_work[index + i] == '-') end_a++; } }*/ var result = new DataTable().Compute(ergebnis_final, null); // Rechnet den Ergebnisstring durch // Funktioniert nicht 100%ig. return Convert.ToDouble(result); // Übergibt des Ergebnis } } }