Projekt wariometru

P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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

NE
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
1

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

Kopiuj
 
        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;
        }

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
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:

Kopiuj
        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.

P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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?

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
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?
Kopiuj
Convert.ToDouble("3.14", CultureInfo.InvariantCulture)
NE
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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ę.

Kopiuj
 
 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);          
            }
        }
P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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ć?

P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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...

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
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?

VarrComodoo
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Bk
  • Postów: 480
1

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

P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
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ę!

P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0
Kopiuj
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

Kopiuj
 Draw(double value)

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

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
1

@Picek91, czyli masz liczby oddzielone przecinkami, tak?

Kopiuj
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.
}
P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Mam teraz coś takiego:

Kopiuj
 
       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? :/

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
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.

P9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
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

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.