Używanie bibliotek

Biblioteka RTadeusiewicz.NN.Controls

Używanie kontrolki rysującej wykresy

Do rysowania wykresów służy kontrolka ChartPlotter. Kontrolka ta potrafi narysować układ współrzędnych i... właściwie cokolwiek. Sama w sobie rysuje osie układu współrzędnych.

To, czy kontrolka rysuje osie układu, kontroluje własność AxesVisibility. Własność TicksVisibility pozwala pokazać lub ukryć podziałkę. Własność TicksDistance określa rozmiar podziałki. Obserwowaną powierzchnię określa własność VisibleSurface. Niestety, nie jest ona edytowalna w designerze, trzeba ją ustawiać bezpośrednio w kodzie.

Dane rysowane na wykresie określane są przez własność DataSeries. Są to serie danych (pojęcie analogiczne do serii danych z Excela). Jest to kolekcja obiektów dziedziczących po klasie DataSeries. Każdy z tych obiektów reprezentuje jedną serię danych, aczkolwiek może równie dobrze reprezentować cokolwiek innego, gdyż w całości odpowiada on za rysowanie. Kolor i grubość linii danej serii możemy ustawić własnościami DataSeries.ForeColor i DataSeries.LineWidth.

Przykład użycia tej kontrolki można zobaczyć w projekcie LibraryTest.

Rysowanie wykresów liniowych

Aby narysować wykres składający się z serii linii (tj. będący łamaną), należy do kolekcji ChartPlotter.DataSeries dodać obiekt klasy ListDataSeries. Klasa ta zawiera własność Data, która zawiera struktury PointF odpowiadające kolejnym wierzchołkom łamanej. Oczywiście aby narysować coś sensownego, kolekcja powinna ta mieć co najmniej 2 elementy.

Inną możliwością jest uzycie obiektu klasy ComputedDataSeries. Jest on przeznaczony do rysowania wykresów funkcji, w szczególności funkcji gładkich. Tutaj rysowany obiekt zadany jest nie serią punktów, lecz funkcją odzwierciedlającą współrzędne poziome na pionowe. Co istotne, funkcja ta jest obliczana dla każdej widocznej kolumny ekranu, dzięki czemu dobrze się skaluje, zachowując gładkość nawet przy zmianie rozmiaru kontrolki macierzystej. Rysowaną funkcję ustawiamy przypisując do własności Function delegata typu ComputedDataSeries.DrawableFunction, czyli funkcji przyjmującej argument typu double i zwracającej wartość typu double.

Jeśli wyświetlana funkcja ma być nie tylko gładka, ale również zależna od jakiegoś "zewnętrznego" parametru, najlepiej jest się posłużyć "obiektem funkcyjnym". W tym celu tworzymy klasę naszej funkcji bazującą na ComputedDataSeries.ParametrizedFunction i przypisujemy obiekt tej klasy do własności ComputedSeries.FunctionObject. Najlepiej to zrozumieć na bazie przykładu zawartego w projekcie LibraryTest.

Rysowanie wykresów punktowych

Inną możliwością jest rysowanie wykresów składających się z serii punktów. W tym celu należy do kolekcji ChartPlotter.DataSeries dodać obiekt klasy PointDataSeries. Zawiera ona kolekcję Points składającą się ze struktur typu PointDataSeries.ChartPoint. Każdy taki element reprezentuje pojedynczy punkt.

Struktura PointDataSeries.ChartPoint zawiera następujące pola:

Coords
współrzędne punktu
Color
kolor punktu; jeśli jest to Color.Empty, oznacza to, że punkt ma być rysowany w kolorze zgodnym z własnością ForeColor serii danych.
DrawLines
określa, czy mają być rysowane linie łączące punkt z początkiem układu współrzędnych i osiami
Shape
kształt punktu: okrąg lub prostokąt.

Wielkość punktów można zmienić własnością PointDataSeries.PointSize (być może w przyszłości każdy punkt będzie mógł mieć rozmiar ustalany indywidualnie).

Rysowanie wykresów funkcji dwuargumentowych

Rysowanie wykresów wizualizujących funkcję dwuargumentową przy pomocy koloru umożliwia klasa Computed2DSeries. Jej użycie jest analogiczne do użycia klasy ComputedDataSeries. Ma ona własne wewnętrzne typy delegatów i funkcji parametryzowanej.

Aby narysować odpowiedź sieci neuronowej o dwóch wejściach i dowolnej ilości wyjść, należy użyć klasy NetworkResponseDrawableFunction. Należy pamiętać tylko o tym, że kolory, jakimi zabarwiane są poszczególne wyjścia, ustawiamy poprzez własność OutputColors. Musi być ich przynajmniej tyle ile wyjść ma sieć.

Inne kontrolki

Kontrolka BorderedControl to po prostu kontrolka zawierająca ramkę.

Klasa WizardForm to klasa pozwalająca na tworzenie kreatorów. Jest to formatka zawierająca przyciski Dalej i Wstecz oraz kontener na panele typu WizardPanel. Aby z nich skorzystać, należy utworzyć własną formatkę dziedziczącą z WizardForm oraz własne panele dziedziczące z WizardPanel, nadpisując metody GetNext() i GetPrevious() oraz własności IsFirst i IsLast. Wymienione metody odpowiadają za utworzenie poprzedniego i następnego panela w reakcji na naciśnięcie odpowiedniego przycisku kreatora, natomiast własności - za określenie, czy panel jest pierwszy lub ostatni.

W formie dziedziczącej po WizardForm wystarczy do własności CurrentPanel przypisać panel, jaki ma być wyświetlany na początku.

Należy na razie uważać na zmienianie rozmiaru formatki - trzeba to robić poprzez przypisanie rozmiaru w kodzie; przypisanie rozmiaru w designerze powoduje zrujnowanie układu kontrolek (to nie jest moja wina, lecz samego designera). Na razie nie znam jeszcze metody na przypisanie rozmiaru skalującego się zgodnie z rozdzielczością DPI ekranu użytkownika. Jakieś pomysły?