Projekt wariometru

0

Witam,
Robię praktyczny model wariometru, który drogą radiową będzie przesyłał dane do komputera.
Na podstawie http://forum.atnel.pl/topic1226.html opracowałem terminal, który te dane odbiera i wyświetla. Chciałbym jednak aby oprócz wykresów i danych w labelach można było obejrzeć dane wyświetlane w postaci "wariometru analogowego"- graficznie.
Niestety moja znajomość C# opiera się głównie na wymienionym wcześniej a nie ma tam słowa o grafice.
Chodzi o to aby było w tym moim terminalu okno wyglądające mniej więcej jak to z załącznika (okrąg) gdzie przy przesłaniu z wariometru danej 3 m/s wskazówka z obrazka przesunęła się na wartość 3 m/s.

Próbowałem zrobić coś na wzór zegarka analogowego z http://www.centrumxp.pl/dotNet/1457,Analogowy-zegarek.aspx#komentarz_54805 , niestety nie udało mi się wykonać tej aplikacji - autor nie zamieścił całości kodu a z dostępnych fragmentów nie potrafię poskładać całości.
Czy ktoś mógłby mi doradzić jakiś fajny poradnik z rysowaniem prostych rzeczy w C# albo powiedzieć jak to zacząć?

Wiem, że muszę narysować okrąg, napisać na nim wartości (od -5 m/s do +5 m/s) a następnie narysować wskazówkę która zaczynała się będzie w środku okręgu a kończyła na x i y wyliczonym z cos i sin i danej odebranej z wariometru. Dobrze myślę? Jak wykonać to w praktyce?
Proszę o pomoc. W załącznikach kod mojego termianalu i prymitywny obrazek przedstawiający jak mniej więcej ma wyglądać ten mój analogowy wariometr.

Z góry dzięki za pomoc,
Picek

1

Na prędce takie coś napisałem. value powinnieneś podawać znormalizowane od 0 do *_myRange

 
        double _myRange = 10.0;
        Pen _myPen = new Pen(new SolidBrush(Color.Black), 2);

        private void Draw(double value)
        {
            System.Drawing.Graphics graphics = this.CreateGraphics();
            Point startOfBox = new Point(50, 50);
            Size boxSize= new Size(200,200);
            System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(
               startOfBox, boxSize);

            graphics.DrawArc(_myPen, rectangle, 180, 180);
            Point centerOfCircle = new Point(startOfBox.X + boxSize.Width/2, startOfBox.Y+boxSize.Height/2);
            
            double angle = GetAngle(value);
            double x2 = centerOfCircle.X - (Math.Cos(angle) * 100);
            double y2 = centerOfCircle.Y - (Math.Sin(angle) * 100);
            Point endPoint = new Point((int)x2, (int)y2);
            graphics.DrawLine(_myPen, centerOfCircle, endPoint);

        }

        private double GetAngle(double value)
        {
              return (Math.PI / _myRange) * value;
        }

0

Wiem, że muszę narysować okrąg, napisać na nim wartości (od -5 m/s do +5 m/s) a następnie narysować wskazówkę która zaczynała się będzie w środku okręgu a kończyła na x i y wyliczonym z cos i sin i danej odebranej z wariometru. Dobrze myślę? Jak wykonać to w praktyce?

Musisz narysować okrąg, napisać na nim wartości, a następnie a następnie narysować wskazówkę która zaczynała się będzie w środku okręgu a kończyła na x i y wyliczonym z cos i sin i danej odebranej z wariometru.

Połóż panel i oprogramuj jego zdarzenie Paint:

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Control control = (Control)sender;
            using (Graphics g = control.CreateGraphics())
            {
                g.Clear(Color.Navy);
                g.DrawEllipse(Pens.Yellow, 0, 0, control.Width-1, control.Height-1);
            }
        }

Szczegóły w dokumentacji. Klawisz F1.

0

Dzięki za odpowiedzi i podpowiedzi!
Pierwsze pytania:
1.(glupie) Jak wywołać twoją funkcję nexodg? Tzn wiem jak tylko nie wiem gdzie. Draw(moje zmienne) tylko gdzie? w zdarzeniu Paint panelu? Po kliknięciu button?
2. Twoja funkcja przyjmuje double a ja dane dostaje w stringu. System.Convert.ToDouble() nie działa. Jak zamienić w takim razie string na double?
3. Jeśli z wariometru dostaję dane, które teoretycznie mogą przyjmować jakiekolwiek wartości, to jak jest znormalizowac?

0
  1. Twoja funkcja przyjmuje double a ja dane dostaje w stringu. System.Convert.ToDouble() nie działa. Jak zamienić w takim razie string na double?
Convert.ToDouble("3.14", CultureInfo.InvariantCulture)
1
Picek91 napisał(a):
  1. Jeśli z wariometru dostaję dane, które teoretycznie mogą przyjmować jakiekolwiek wartości, to jak jest znormalizowac?

Poza limitami odrzuć, sam limit przesuń.
Przykład zakres -5 -- 5,
wartość -3 --> 0.. 2 10.
wartość 3 --> 0.. 8 10.
wartość maksymalna 5 --> 0... 10.
wartośc poza zakresem 12 --> 10.
jeśli jednak chcesz by odpowiednio się skalowało tzn wykres był logarytmiczny coś w stylu:
wartość -100,-50,-30,-20,-15.. tu mega gęsto 0 tu dalej gesto +15, 20,30,50,100 to ja Ci już nie pomogę.

 
 private double Normalize(double value, double min, double max)
        {
            if (value < min)
                return min;
            else if (value > max)
                return max;
            else
            {
               return value + Math.Abs(min);          
            }
        }
0

@Azarien
Próbowałem przekonwertować tak jak powiedziałeś:

Error 1 The name 'CultureInfo' does not exist in the current context C:...\Terminal\Form1.cs 125 53 Terminal

Bez tego CultureInfo:
Nie można rzutować obiektu typu 'System.String[]' na typ 'System.IConvertible'.

Zatem w jaki sposób to przekonwertować?

0

Dzięki Azarien za pomoc.
Podczas kompilacji nie wyskakuje żaden błąd.
Funkcje wywoływałem pod buttonem i przy panel paint ale ani w jednym ani w drugim przypadku nic nie zaczęło się rysować. Jak wywołać tą funkcję?

Poza tym po rozłączeniu portu debuger wywala:
Nie można rzutować obiektu typu 'System.String[]' na typ 'System.IConvertible'.
więc chyba i tak coś jest nie tak z tą konwersją na duble...

0
Picek91 napisał(a):

Nie można rzutować obiektu typu 'System.String[]' na typ 'System.IConvertible'.

Wszystko się zgadza. String jest IConvertible, ale String[], czyli tablica stringów już nie. Czemu i na co chcesz konwertować tablicę stringów?

1

Chciałbym tylko wtrącić że zegarek z CentrumXP działa:

0

@somekind
Tablicę stringów chcę przekonwertować na double.
Tablicę stringów bo w takiej formie dostaję dane z Atmegi, na double, ponieważ taki typ przyjmuje f-ja Nexodg

0
Picek91 napisał(a):

Tablicę stringów chcę przekonwertować na double.

Ale tablicę napisów możesz skonwertować na tablicę liczb, a nie na jedną liczbę!

0
printf("%0.1f,%0.2f,%0.1f,%0.1f,\r\n", (double)temperature/10,(double)pressure/100,(double)altitude,(double)velocity); 

W ten sposób wysyłam dane z Atmegi do termianala. Do mojego graficznego wariometru potrzebna mi dana po ostatnim przecinku i to chciałbym wrzucić do funkcji Nexodg

 Draw(double value)

Jakiś pomysł jak to zrobić bo ja już się gubię.

1

@Picek91, czyli masz liczby oddzielone przecinkami, tak?

string[] dane = napisZAtmegi.Split(',');
for (int i = 0; i < dane.Length; i++)
{
    // tutaj konwersja z dane[i] na double i wywołanie funkcji przyjmującej double.
}
0

Mam teraz coś takiego:

 
       private void rx_parse(object sender, EventArgs e)
        {
 
            tab_size++;
 
            string[] dane = new string[5];
            dane = rx_str.Split(',');
 
            /**WYŚWIETLANIE WYNIKOW**/
 
            textBox1.Text = dane[0] + "°C";
            textBox2.Text = dane[1] + "hPa";
            textBox3.Text = dane[2] + "m";
            textBox4.Text = dane[3] + "m/s";
//-------------------------------------------------------------------------------------------------
            Draw(Normalize(Convert.ToDouble(dane[3], CultureInfo.InvariantCulture), -5, 5));    //F-ja o którą mi chodzi.
//-------------------------------------------------------------------------------------------------
            /**WYKRESY**/
            chart1.Series["Series1"].Points.AddY(dane[0]);
            chart2.Series["Series1"].Points.AddY(dane[1]);
            chart3.Series["Series1"].Points.AddY(dane[2]);
            chart4.Series["Series1"].Points.AddY(dane[3]);
            

            notifyIcon1.Text = "T: " + dane[0] + "P: " + dane[1] + "H: " + dane[2] + "V: " + dane[3];
 
            richTextBox1.AppendText(rx_str);

            



            Array.Resize(ref temperatura, tab_size); // Cykliczne powiększanie rozmiaru tablicy
            Array.Resize(ref cisnienie, tab_size); // j.w
            Array.Resize(ref wysokosc, tab_size);  // j.w
            Array.Resize(ref predkosc, tab_size); // j.w
   


            temperatura[index] = dane[0];
            cisnienie[index] = dane[1];
            wysokosc[index] = dane[2];
            predkosc[index] = dane[3];
            index++;

            for (int n = 0; n < tab_size; n++)
            {
                dataGridView1.Rows.Add(1);
                dataGridView1.Rows[n].Cells[0].Value = temperatura[n];
                dataGridView1.Rows[n].Cells[1].Value = cisnienie[n];
                dataGridView1.Rows[n].Cells[2].Value = wysokosc[n];
                dataGridView1.Rows[n].Cells[3].Value = predkosc[n];
            }



        }

Kompiluje się ładnie, wszystko gra, jednak nadal nic mi się nie wyświetla ani maluje. Wiem, że to na pewno jakieś głupstwo ale jak wywołać tą funkcję żeby namalowało mi ten wariometr? :/

0

@Picek91, czemu Ci nie rysuje to nie wiem. Mogę Ci tylko powiedzieć, że przez to, że nie programujesz obiektowo, ten kod jest strasznie zamotany. A już najgorsze jest chyba to Array.Resize. Użyj listy (typu List<T>) zamiast tablicy i nie kombinuj w ten sposób.

0

Szczerze mówiąc to z programowania jestem zielony zupełnie... sam bym tego nie napisał i wszystko jest na wzór z http://forum.atnel.pl/topic1226.html ...
Nie mam pojęcia jak to zrobić żeby mi rysowało

1 użytkowników online, w tym zalogowanych: 0, gości: 1