/* Achsendarstellung sowie Skalierung der Messwerte im Diagramm
* Von dieser Klasse werden 3 Objekte generiert: Frequenz, Amplitude, Phase
*/
#include "PiezoMess.h"
enum{
TICKLEN=14,
GAP=1, // Pixel zwischen Text und Skalenstrich
};
double AXIS::FromNative(double v) const{
return a+v*(e-a); // TODO: Logarithmisch!
}
double AXIS::ToNative(double v) const{
return (v-a)/(e-a); // TODO: Logarithmisch!
}
double AXIS::begin() const{
return a;
}
double AXIS::next(double z) const{
return log ? z*tick : z+tick;
}
bool AXIS::okay() const{
return log ? a>0 && e>0 && tick>0 && tick!=1 && (tick>1 ? e>a : e<a)
: a*tick < e*tick; // tick==0 oder irgendein NaN produziert False
}
bool AXIS::beyond(double z) const{
return e<a ? z<e : z>e;
}
// Einen Teiler mit der Mantisse 1, 2 oder 5 funden
// x>0, pot ist Startwert der Suche, bspw. 1.0
// Heraus kommt: x/2.5 < Ergebnis <=x, x>0
static double FindDivider(double x, double pot) {
if (x<=0) return pot; // Fehler!
if (x < pot) return FindDivider(x,0.1F*pot); // nach unten suchen
else if (x <= 2*pot) return pot;
else if (x <= 5*pot) return 2*pot;
else if (x <= 10*pot) return 5*pot;
else return FindDivider(x,10*pot); // nach oben suchen
}
void AXIS::AutoCalcTicks() {
if (log) {
double q=e/a; // Quotient wenn logarithmisch
tick=pow(q,0.1); // 10 Abschnitte, 11 Skalenstriche (einfach!)
}else{
double d=e-a; // Differenz
tick=FindDivider(d/10,1); // mindestens 10 Haupt-Striche
}
}
void XAXIS::Draw(HDC dc) const{
TCHAR s[64];
int i=FloatToString(a,nk,s,elemof(s));
UINT ta=TA_RIGHT; // Schrift-Richtung
if (mirror) ta=TA_LEFT;
SetTextColor(dc,GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(dc,GetSysColor(COLOR_WINDOW));
bool EinheitAnZahl= // lt. DIN müssen °, ' (Minuten) und " (Sekunden) an die Zahl
unit[1]==0 && (unit[0]==T('°') || unit[0]=='\'' || unit[0]=='"');
int y=bbox.top+TICKLEN; // Schrift-Kante
if (mirror) y=bbox.bottom-TICKLEN; // hier: obenseitige Skale (Ticks unten, Schrift darüber)
double scale=(bbox.width()-1)/(log?::log(e/a):(e-a));
POINT pt[2];
pt[0].y=bbox.top;
pt[1].y=y;
if (mirror) { // immer von oben nach unten zeichnen lassen (letzter Punkt wird von PolyLine nicht gesetzt)
pt[0].y=y;
pt[1].y=bbox.bottom;
}
y+=mirror ? -GAP : +GAP;
SetTextAlign(dc,ta);
SelectFont(dc,gdi.fntScale[1]);
SIZE size;
GetTextExtentPoint32(dc,s,i,&size);
if (okay()) for (double z=begin();!beyond(z); z=next(z)) {
pt[1].x=pt[0].x=bbox.left+lrint(scale*(log?::log(z/a):z-a));
Polyline(dc,pt,2);
i=FloatToString(z,nk,s,elemof(s));
ExtTextOut(dc,pt[0].x-size.cy/2,y,0,&bbox,s,i,NULL);
if (pt[0].x>=bbox.right) break;
}
SetTextAlign(dc,TA_CENTER);
ExtTextOut(dc,bbox.left+size.cy/2,bbox.midy(),0,&bbox,unit,lstrlen(unit),NULL);
SelectFont(dc,gdi.fntScale[2]);
y=bbox.top;
if (!mirror) SetTextAlign(dc,TA_CENTER|TA_BOTTOM), y=bbox.bottom;
int l=lstrlen(name)+3;
PTSTR p=new TCHAR[l];
l=_sntprintf(p,l,T(" %s "),name);
ExtTextOut(dc,bbox.midx(),y,0,&bbox,p,l,NULL);
delete[] p;
}
void YAXIS::Draw(HDC dc) const{
TCHAR s[64];
int i=FloatToString(a,nk,s,elemof(s));
UINT ta=TA_RIGHT; // Schrift-Richtung
if (mirror) ta=TA_LEFT;
SetTextColor(dc,GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(dc,GetSysColor(COLOR_WINDOW));
TCHAR const *unit = trace->unit;
bool EinheitAnZahl= // lt. DIN müssen °, ' (Minuten) und " (Sekunden) an die Zahl
unit[1]==0 && (unit[0]==T('°') || unit[0]=='\'' || unit[0]=='"');
// Dieser Murks geht nicht mit UTF-8!
int x=bbox.right-TICKLEN; // Schrift-Kante
if (mirror) x=bbox.left+TICKLEN; // hier: rechtsseitige Skale (Ticks links, Schrift rechts daneben)
// Skalenstriche
double scale=(bbox.top-bbox.bottom+1)/(log?::log(e/a):e-a); // negativ!
POINT pt[2];
pt[0].x=x;
pt[1].x=bbox.right;
if (mirror) { // immer von links nach rechts zeichnen lassen (letzter Punkt wird von PolyLine nicht gesetzt)
pt[0].x=bbox.left;
pt[1].x=x;
}
x+=mirror ? +GAP : -GAP;
SetTextAlign(dc,ta);
SelectFont(dc,gdi.fntScale[0]);
SIZE size;
GetTextExtentPoint32(dc,s,i,&size);
if (okay()) for (double z=begin(); !beyond(z); z=next(z)) {
pt[1].y=pt[0].y=bbox.bottom-1+lrint((log?::log(z/a):z-a)*scale);
Polyline(dc,pt,2);
// Beschriftung
i=FloatToString(z,nk,s,elemof(s));
if (EinheitAnZahl) s[i++]=unit[0];
ExtTextOut(dc,x,pt[0].y-size.cy/2,0,&bbox,s,i,NULL);
}
// Einheit
if (!EinheitAnZahl) {
SetTextAlign(dc,TA_CENTER);
ExtTextOut(dc,bbox.midx(),bbox.top+size.cy/2,0,&bbox,unit,lstrlen(unit),NULL);
}
// Name
SelectFont(dc,gdi.fntScale[3]);
x=bbox.left;
if (mirror) SetTextAlign(dc,TA_CENTER|TA_BOTTOM), x=bbox.right;
SetTextColor(dc,trace->color);// Skalenfarbe
SetBkColor(dc,0); // schwarz
int l=lstrlen(trace->name)+3;
PTSTR p=new TCHAR[l];
l=_sntprintf(p,l,T(" %s "),trace->name);
ExtTextOut(dc,x,bbox.midy(),0,&bbox,p,l,NULL);
delete[] p;
}
| Detected encoding: ANSI (CP1252) | 4
|
|
|