TAChart Tutorial: Function Series/fi
│
English (en) │
suomi (fi) │
Johdanto
Kävitkö läpi aloitusoppaan? Siinä oppaassa oltiin käytetty joitakin matemaattisia funktioita näyttämään TAChart:n peruskäyttöä viivakuvaajan avulla. Viivakuvaaja, ei kuitenkaan ole paras valinta näyttämään matemaattisia funktioita. TFuncSeries
(funktiokuvaaja) sopii paljon paremmin tähän tarkoitukseen. Tämä on kuvaaja, joka - ensisilmäyksellä - näyttää tavalliselta viivakuvaajalta. Mutta taustalla, se on täysin erilainen. Se ei saa sen dataa ChartSource:sta, vaan matemaattiselta funktiolta. Aina kun kuvaaja tarvitsee tietoja se kutsuu OnCalculate
tapahtumaa, jossa käyttäjä voi siirtää funktion arvoja pyydettyyn x: n arvoon. Tämä säästää muistia, funktion arvoja ei tarvitse varastoida. Mutta ennen kaikkea, se mahdollistaa laskea funktion arvot zoomaus tason ja kaavion koon mukaan, riittävän kapein välein, niin että kuvaajan käyrä on "sileä" suurillakin suurennoksilla.
Valmistautuminen
Aloitetaan uusi projekti tuomalla vakio TChart
komponentti lomakkeelle. Käytetään seuraavia asetuksia:
- Align:
alClient
- BackColor:
clWhite
- BottomAxis:
Grid.Color = clSilver
,Title.Caption = 'x'
,Title.Visible = true
,Title.LabelFont.Style = fsBold
- LeftAxis:
Grid.Color = clSilver
,Title.Caption = 'y'
,Title.Visible = true
,Title.LabelFont.Style = fsBold
Näiden muutosten jälkeen lomake näyttää samantapaiselta kuin vasempi kuva:
Lisätään TFuncSeries
Aluksi piirretään sinifunktio y = sin(x). Tupla-klikkaa kaaviota, muokkaa kuvaajia ikkuna avautuu. Klikkaa "lisää" ja valitse "funktiokuvaaja " alasveto luettelosta. Kaaviossa nyt näytetään viivaa joka lähtee vasemmasta alakulmasta ja menee oikeaan yläkulmään (se esittää funktiokuvaajaa).
Muutetaan kuvaajan väri punaiseksi. Funktiokuvaajalla ei ole SeriesColor
ominaisuutta, mutta sillä on ominaisuus Pen
tähän tarkoitukseen: Aseta Pen.Color
arvoon clRed
.
Seuraavaksi mennään komponenttimuokkaimen "Tapahtumat" välilehdelle ja tuplaklikataan tapahtumaa OnCalculate
. Tämä on se metodi, jossa me määrittelemme funktion toiminnan. OnCalculate
metodia kutsutaan aina kun kuvaaja tarvitsee y-arvon annetulle x-arvolle:
<syntaxhighlight lang=pascal>
procedure TForm1.Chart1FuncSeries1Calculate(const AX: Double; out AY: Double);
begin
AY := sin(AX);
end; </synyaxhighlight>
Kun tämä käännetään nähdään sinifunktio. Mutta se ei koko aalto - koska ei asetettu akseleita, x:n arvot ovat ainoastaan väliltä -1 ja +1, oletuksena tyhjän x-akselin laajuudessa.
Laajuuden asettaminen
X-laajuus
Laajemman akselin alueen saamiseksi on kaksi vaihtoehtoa: voidaan asettaa kuvaajan extent tai kaavion extent. On hienoisia eroja molemmissa tapauksissa yksinkertaisessa kaaviossakin, mutta ne eivät näy ja siksi siitä ei enempää tässä. Mennään komponenttimuokkaimeen, valitaan kuvaajan ominaisuus Extent
, asetetaan akseli alkamaan XMin
vaikkapa -10 ja loppumaan XMax
+10. Aktivoi nämä akselin rajat asettamalla UseXMin
ja UseXMax
arvoon true
. Kun nyt käännetään niin nähdään sinifunktion -10 ja 10 välillä.
Y -laajuus
Miksi emme leiki toiminnolla hieman jotta nähdään, mitä tapahtuu? Siirry OnCalculate
tapahtumaan uudelleen ja moninkertaista sinifunktio kahdella:
<syntaxhighlight lang=pascal>
procedure TForm1.Chart1FuncSeries1Calculate(const AX: Double; out AY: Double);
begin
AY := 2*sin(AX);
end; </synyaxhighlight>
Oho - funktiokuvaaja ei automaattisesti päivitä y :n laajuutta! Tämä pätee vanhassa Lasaruksen versiossa 1.0. Nykyään FuncSeries
:ssä on ominaisuus ExtentAutoY
. Jos se on asetettu arvoon true
niin se toimeenpanee automaattisen laskemisen y:n laajuudelle. Huomaa, että ominaisuus pätee vain, jos molemmat Extent.UseXMin
ja Extent.UseXMax
ovat asetettu arvoon true
.
Jos käytössä on Lazaruksen vanha versio niin extent pitää asettaa käsin: Valitse kuvaajan Extent
uudelleen asettamalla YMin
arvoon -2,YMax
arvoon 2 ja UseYMin
sekä UseYMax
arvoon true
. Tämä näyttää koko sinikäyrän amplitudilla 2.
Zoomaus
Nyt tarkastellaan johdannossa mainittua seikkaa että funktiokuvaaja on aina tarkka, vaikka suurennos olisi suuri. Ero nähdään kun piirretään sinifunktion toisen kerran, mutta nyt se tehdään viivakuvaajalla joka piirtää vain ennalta määriteltyihin segmentteihin.
Lisää "viivakuvaaja" kaavioon, aseta sen Pen.Style
arvoon psDash
ja lisää seuraava koodi lomakkeen onCreate tapahtumakäsittelijään jossa määritellään kuvaajan tiedot:
<syntaxhighlight lang=pascal>
procedure TForm1.FormCreate(Sender: TObject);
const
N = 100; XMIN = -10; XMAX = 10;
var
i: Integer; x: Double;
begin
for i:=0 to N-1 do begin x := XMIN + (XMAX - XMIN) * i / (N-1); Chart1LineSeries1.AddXY(x, 2*sin(x)); end;
end; </synyaxhighlight> Kun ohjelma käännetään ja ajetaan niin punaisen funktiokuvaajan ja mustan viivakuvaajan käyrät ovat päällekkäin, käyrät on vaikea erottaa. Jos zoomaat kaavion: pitäen hiiren vasenta näppäintä alhaalla ja vetämällä pieni suorakulmio lähelle yhtä sinifunktion maksimihuippua ( vedä hiirellä ylhäältä-vasemmalta oikeaan alakulmaan jolloin saadaan zoomaus aikaan). Kun vapautat hiiren näet nyt zoomatun suorakulmion. Jos suurennus on riittävän suuri, näet segmentit viivakuvaajassa, mutta funktiokuvaaja on edelleen tarkka.
Mikä on syy, miksi funktiokuvaaja on niin sileä jopa äärimmäisissä suurennuksissa? Tämä johtuu siitä, että funktio on laskettu hyvin pienin välein. Tämä määritellään TFuncSeries
ominaisuudessa Step
. Tässä oleva numero on näytön pikseleitä ja siksi tasaisuus on riippumaton zoomauksesta. Useimmissa toiminnoissa sen oletusarvo 2 on hyvä kompromissi lähes täydelliseen resoluutioon ja piirtämisen nopeuteen.
Ennen kuin jatketaan, poista viivakuvaaja emme tarvitse sitä enää. Poista myös FormCreate tapahtumankäsittelijä.
Domain exclusions
Piirretään y = tan(x)
Tässä harjoituksessa haluamme piirtää eri funktion, y = tan(x). Voimme helposti mukauttaa se tähän projektiin muuttamalla toiminnon OnCalculate
tapahtumakäsittelijää (Huom. pitää lisätä myös math
käännösyksikkö uses
lausekkeeseen):
<syntaxhighlight lang=pascal>
procedure TForm1.Chart1FuncSeries1Calculate(const AX: Double; out AY: Double);
begin
AY := tan(AX);
end; </synyaxhighlight>
Kaavio näyttää hyvältä ensi silmäyksellä, mutta kun muistaa joitakin perusasioita tan funktiosta koulusta huomaa että (melkein) pystyjuovat lähellä ±1.6, ±4.7, ±7.9 eivät ole oikeita. Toimintoa ei ole määritelty näissä paikoissa (tarkalleen (n+1/2)π). Kuvaajaa ei pitäisi olla siellä. Koska funktiokuvaaja ei "tiedä" näistä katkoksista, se piirtää yhteyden viimeisen ja ensimmäisen lasketun pisteen välille ennen ja jälkeen epäjatkuvuuden.
TFuncSeries
tarjoaa niin sanottua DomainExclusions
joka ratkaisee tämän kysymyksen. Nämä ovat kohtia ja alueita, joissa toimintoa ei ole laskettu ja ole piirretty. Tällä hetkellä DomainExclusions
eivät näy komponenttimuokkaimessa, vaan se on käytettävä koodin suorituksen aikana kutsumalla menetelmillä AddPoint
tai AddRange
. .
Tan funktion tapauksessa, lisätään seuraava koodi lomakkeen onCreate tapahtumakäsittelijään jossa otetaan edellä mainitut seikat laskettaessa huomioon : <syntaxhighlight lang=pascal> procedure TForm1.FormCreate(Sender: TObject); begin
with Chart1FuncSeries1.DomainExclusions do begin AddPoint(pi/2); AddPoint(-pi/2); AddPoint(3*pi/2); AddPoint(-3*pi/2); AddPoint(5*pi/2); AddPoint(-5*pi/2); end;
end; </synyaxhighlight>
Kaavio on nyt täydellinen?
On kuitenkin huomioitava, että koodi FormCreate
metodissa on liian erityinen ja on oikea vain kun x-akselin vaihtelevat -10:stä 10:n. Oletetaan käyttäjä voisi loitontaa tai voisi muuttaa akselin rajat jollakin muulla tavalla. Sitten nämä domain poikkeukset ei välttämättä sovi enää. Siksi pitäisi antaa hieman yleisempi menetelmä, ehkä "UpdateDomainExclusions
" ja kutsua sitä tarvittaessa. Ensimmäinen ajatus olisi käyttää kaavion OnExtentChanged
tapahtumassa. Menemättä yksityiskohtiin, mutta tämä saattaa aiheuttaa riippuvuuksia joissakin olosuhteissa, koska tämä tapahtuma tehdään kaavion piirtämisen jälkeen. Nykyisissä Lazarus versioissa on kuitenkin uudempi tapahtuma OnExtentChanging
joka sopii paremmin, koska sitä kutsutaan ennen piirtämistä. Lazaruksen vanhoissa versioissa voi käyttää tapahtuman käsittelijä TChart.OnAfterDrawBackwall
vaikka sen nimi ei ole intuitiivinen tähän tarkoitukseen. Ei saa unohtaa kutsua DomainExclusions.Clear
välttämään lisäämästä samoja asioita uudestaan ja uudestaan.
<syntaxhighlight lang=pascal> procedure TForm1.UpdateDomainExclusions; var
ex: TDoubleRect; // unit TAChartUtils.pas x: Integer;
begin
ex := Chart1.CurrentExtent; Chart1.DisableRedrawing; try with Chart1FuncSeries1.DomainExclusions do begin Clear; for x := Floor(ex.a.x / Pi - 0.5) to Ceil(ex.b.x / Pi + 0.5) do AddPoint((x + 0.5) * Pi); end; finally Chart1.EnableRedrawing; end;
end; </synyaxhighlight>
Piirretään y = ln(x)
Viimeisessä harjoituksessa lisätään toinen funktio y = ln (x). Kaksoisklikkaa kaaviota uudelleen ja muokkaa kuvaajia ikkunassa lisää toinen funktiokuvaaja. Aseta sen väriksi clBlue
ja kirjoita seuraava OnCalculate
tapahtumakäsittelijä joka kertoo kuvaajalle log funktion piirtämisen:
<syntaxhighlight lang=pascal> procedure TForm1.Chart1FuncSeries2Calculate(const AX: Double; out AY: Double); begin
AY := ln(AX);
end; </synyaxhighlight>
Mutta kun ohjelma ajetaan se kaatuu, koska se sai liukulukupoikkeuksen! Mistä se tuli? Koska x-akselin alkaa arvosta -10 ja logaritminen funktio voi laskea ainoastaan positiivisia x-arvoja. Mitä tässä tapauksessa voidaan tehdä? Vastaus on domain poikkeukset, jälleen. Kielletään vain funktion laskenta negatiivisillä arvoilla ja kun x = 0. Tämä voidaan saavuttaa lisäämällä välille -INF - 0 kuvaajaan domain poikkeuksia. Metodi AddRange
hoitaa myös päätepisteiden välin, joten emme tarvitse mitään erityistä kun x = 0. Muutetaan lomakkeen OnCreate
tapahtumakäsittelijä seuraavasti:
<syntaxhighlight lang=pascal> procedure TForm1.FormCreate(Sender: TObject); begin
with Chart1FuncSeries1.DomainExclusions do begin AddPoint(pi/2); AddPoint(-pi/2); AddPoint(3*pi/2); AddPoint(-3*pi/2); AddPoint(5*pi/2); AddPoint(-5*pi/2); end; { ... tai tämän tilalla olisi parempi olla erillinen UpdateDomainExclusions procedure mistä aiemmin mainittiin tekstissä} with Chart1FuncSeries2.DomainExclusions do begin AddRange(NegInfinity, 0); end;
end; </synyaxhighlight>
Nyt ohjelma toimii hyvin.
Eräs asia joka pitää mainita, on DomainExclusions
ominaisuus Epsilon
. Tämä arvo ohjaa etäisyyttä päätepisteen ulkopuolelle välin ja viimeinen piirretään toiminnon kohta. Sen oletusarvo 1e-6
on sopiva useimmissa tapauksissa, mutta voit lisätä sen ääretön-tyypin epäjatkuvuudet (y = tan(x)
), tai alentaa sitä mallintaa auki ulkopuolelle välein. Yksi esimerkki Jälkimmäisessä tapauksessa on funktio y = sqrt(x)
, jota ei ole määritelty negatiivisia numeroita, mutta on määritelty x = 0
(toisin kuin logaritmifunktiota); Tässä tapauksessa toimialueen ulkopuolelle ei saisi sisältää x = 0
, mutta koska välein DomainExclusions
suljetaan aina voit näyttää tässä vaiheessa kaavion asettamalla Epsilon = 0
.
Viimeistely
Legend
Ennen päätämme voimme soveltaa joitakin parannuksia. Älä näytä useita käyriä samassa kaavion ilman kuvaajien otsikkopalkkia (legend), ilman sitä ei olisi mitään keinoa erottaa ne toisistaan. Anna funktion nimi Title
ominaisuuteen kummallekin kuvaajalle ja aseta niiden legend ominaisuuden Visible
arvoon true
.
Lisätään koordinaatti akselit (TConstantLineSeries)
Graafisissa matemaattisissa funktiossa usein akselit risteävät origossa. TAChart on mahdollisuus siirtää akseleita poispäin reunasta ominaisuudella Position
. Tässä tapauksessa mennään toisella tavalla:
Avaa muokkaa kuvaajia ikkuna uudelleen ja lisätään kaksi "kiinteä viiva" kuvaajaa . Nämä ovat hyvin yksinkertaisia kuvaajia, joka näyttää yhdensuuntainen koordinaatiston akseleita. Niiden sijainti määritellään ominaisuudessa Position
, niiden suunta - vaaka- tai pystysuoraan LineStyle
. Ei ole mitään tekemistä sen kanssa Position
jonka oletusarvo on 0. Täytyy vain asettaa yhden kuvaajan LineStyle
arvoon lsHorizontal
ja toisen arvoon lsVertical
. TConstantLineSeries kuvaajalla on myös arrow eli nuoli , joka voidaan aktivoida asettamalla Arrow.Visible
arvoon true
. Kokeile Arrow
ominaisuuksia Length
, Width
ja BaseLength
jotta löydät muodon joka on sopiva.
Lopuksi kannattaa laittaa kiinteän viivakuvaajien omaisuus Legend.Visible
arvoon false
muuten tulee kaksi tunnistamatonta merkintää legend otsikkopalkkiin.
Tässä lopputulos:
Lähdekoodi
Lähdekoodin lopullinen versio tämän opetusohjelman projektista löytyy TAChart asennuksen kansiosta tutorials/func_series .