public class XYGraphic : Control { private int nr = 0; private Gitter gitter = new Gitter(); private Achse xAchse = new Achse(); private Achse yAchse = new Achse(); private Graphic graphic = null; private FormattedText formattedText; private double fontHeight = 0.0; private List coords = null; private Pen penBlack = new Pen(Brushes.Black, 1); public XYGraphic() { graphic = new Graphic(gitter, xAchse, yAchse); Color brushText = Colors.Black; formattedText = new FormattedText("888.88", CultureInfo.GetCultureInfo("DE-de"), FlowDirection.LeftToRight, new Typeface("Verdana"), 11, new SolidColorBrush(brushText)); // text.brushText)); fontHeight = formattedText.Height; graphic.setFormattedText(this.formattedText); } public void setGraphic(String title, String xname, String yname, double xa, double xsw, double xe, double ya, double ysw, double ye) { this.gitter.title = title; this.xAchse.bezeichnung = xname; this.yAchse.bezeichnung = yname; this.xAchse.xa = xa; this.xAchse.xsw = xsw; this.xAchse.xe = xe; this.xAchse.setNachkommastellen(); this.yAchse.xa = ya; this.yAchse.xsw = ysw; this.yAchse.xe = ye; this.yAchse.setNachkommastellen(); // this.f = new Font("Verdana", Font.PLAIN, 14); coords = null; // muss erst gesetzt werden graphic.coords = null; this.InvalidateVisual(); } public void setCoords(List coords) { this.coords = coords; graphic.coords = coords; this.InvalidateVisual(); } // setCoords protected override void OnRender(DrawingContext dc) { base.OnRender(dc); double width = this.ActualWidth; double height = this.ActualHeight; // dc.DrawLine(penBlack, new Point(10, 10), new Point(100, 200)); bool b1 = this.ActualWidth > 0; bool b2 = this.ActualHeight > 0; if (!b1 || !b1) return; gitter.pixY0 = fontHeight + fontHeight + fontHeight; // Ziffern Xname gitter.pixHeight = this.ActualHeight - gitter.pixY0 - (fontHeight + fontHeight); gitter.pixX0 = formattedText.Width; gitter.pixWidth = this.ActualWidth - gitter.pixX0 - gitter.pixX0; gitter.MaxY = this.ActualHeight; // y inverted gitter.MaxX = this.ActualWidth; gitter.pixTop = gitter.pixY0 + gitter.pixHeight; // obere Rahmenhoehe graphic.setFactors(); // penBlack.DashStyle = DashStyles.Dash; Rect rect = new Rect(0, 0, Width, Height); dc.DrawRectangle(Brushes.Green, penBlack, rect); graphic.drawGitter(dc); graphic.drawCoords(dc); } public override String ToString() { StringBuilder sb = new StringBuilder(); sb.AppendLine("Xa: " + 0.0); sb.AppendLine("Xsw: " + 1.0); sb.AppendLine("Xe: " + 10.0); sb.AppendLine("Ya: " + 0.0); sb.AppendLine("Ysw: " + 1.0); sb.AppendLine("Ye: " + 10.0); if (coords != null) { PointXY p; for (int i = 0; i < coords.Count; i++) { p = coords[i]; sb.AppendLine("x[" + i + "] = " + p.x); sb.AppendLine("y[" + i + "] = " + p.y); } } return sb.ToString(); } // ----------------------- class Graphic { public FormattedText formattedText=null; public double fontheight = 0.0; public Gitter gitter = null; public Achse xAchse = null; public Achse yAchse = null; private double faktorGowXPlus = 0.0; private double faktorGowXMinus = 0.0; private double faktorGowYPlus = 0.0; private double faktorGowYMinus = 0.0; public List coords = null; private Pen penBlack = new Pen(Brushes.Black, 1); private Pen penBlue = new Pen(Brushes.Blue, 2); private Point p1 = new Point(); private Point p2 = new Point(); public Graphic(Gitter gitter, Achse xAchse, Achse yAchse) { this.gitter = gitter; this.xAchse = xAchse; this.yAchse = yAchse; } public void setFormattedText(FormattedText formattedText) { this.formattedText = formattedText; this.fontheight = formattedText.Height; } public void setFactors() { this.faktorGowXPlus = gitter.pixWidth / (xAchse.xe - xAchse.xa); this.faktorGowXMinus = gitter.pixWidth / (xAchse.xa - xAchse.xe); this.faktorGowYPlus = gitter.pixHeight / (yAchse.xe - yAchse.xa); this.faktorGowYMinus = gitter.pixHeight / (yAchse.xa - yAchse.xe); } internal void drawGitter(DrawingContext dc) { Rect rect = new Rect(gitter.pixX0, gitter.MaxY - gitter.pixTop, gitter.pixWidth, gitter.pixHeight); dc.DrawRectangle(null, penBlack, rect); if (xAchse.xa < xAchse.xe) { if (xAchse.xsw < 0.0) xAchse.xsw = Math.Abs(xAchse.xsw); } else { if (xAchse.xsw > 0.0) xAchse.xsw = -xAchse.xsw; } if (xAchse.xsw > 0) drawXLinesPlus(dc); else drawXLinesMinus(dc); drawYLines(dc); drawTextZentr(dc,14, gitter.pixX0 + (gitter.pixWidth * 0.5), 20, gitter.title); drawTextZentr(dc,11, gitter.pixX0 + (gitter.pixWidth * 0.5), gitter.MaxY - (gitter.pixY0 - fontheight - fontheight - 4), xAchse.bezeichnung); drawTextZentrY(dc, 20, gitter.MaxY - (gitter.pixY0 - gitter.pixHeight * 0.5 - 4), yAchse.bezeichnung); // drawTextZentrY(dc, 220, gitter.MaxY - (gitter.pixY0 - gitter.pixHeight * 0.5 - 4), yAchse.bezeichnung); } internal void drawXLinesPlus(DrawingContext dc) { /* xee=ende da Rundungsfehler auftreten k÷nnen */ int i = 0; int xlen = 5; double pos, ix; bool erster = true; bool letzter = false; double x = xAchse.xa; double xee = xAchse.xe + xAchse.xsw * 0.01; double ymin = gitter.MaxY - (gitter.pixY0 - xlen); double ymax = gitter.MaxY - (gitter.pixTop); double yfont = gitter.MaxY - (gitter.pixY0 - xlen - fontheight); while (x <= xee) { i++; pos = GOWandleX(x); ix = gitter.pixX0 + pos; letzter = (x + xAchse.xsw) > xee; if (erster) { p1.X = gitter.pixX0; p1.Y = ymin; p2.X = gitter.pixX0; p2.Y = gitter.pixY0; dc.DrawLine(penBlack, p1, p2); drawTextZentr(dc, 11, gitter.pixX0, yfont, getNumberWithFormat(x, xAchse.nachkommastellen)); } else if (letzter) { p1.X = gitter.pixX0 + gitter.pixWidth; p1.Y = ymin; p2.X = gitter.pixX0 + gitter.pixWidth; p2.Y = gitter.pixY0; dc.DrawLine(penBlack, p1, p2); drawTextZentr(dc, 11, gitter.pixX0 + gitter.pixWidth, yfont, getNumberWithFormat(x, xAchse.nachkommastellen)); } else { p1.X = ix; p1.Y = ymin; p2.X = ix; p2.Y = ymax; dc.DrawLine(penBlack, p1, p2); drawTextZentr(dc, 11, ix, yfont, getNumberWithFormat(x, xAchse.nachkommastellen)); } x += xAchse.xsw; erster = false; } } // drawXLinesPlus internal void drawXLinesMinus(DrawingContext dc) { /* xee=ende da Rundungsfehler auftreten k÷nnen */ int i = 0; int xlen = 5; double pos, ix; bool erster = true; bool letzter = false; double x = xAchse.xa; // xa > xe double xee = xAchse.xe + xAchse.xsw * 0.01; double ymin = gitter.MaxY - (gitter.pixY0 - xlen); double ymax = gitter.MaxY - (gitter.pixTop); double yfont = gitter.MaxY - (gitter.pixY0 - xlen - fontheight); while (x >= xee) { i++; pos = GOWandleX(x); ix = gitter.pixX0 + pos; letzter = (x + xAchse.xsw) < xee; if (erster) { p1.X = gitter.pixX0; p1.Y = ymin; p2.X = gitter.pixX0; p2.Y = gitter.pixY0; dc.DrawLine(penBlack, p1, p2); drawTextZentr(dc, 11, gitter.pixX0, yfont, getNumberWithFormat(x, xAchse.nachkommastellen)); } else if (letzter) { p1.X = gitter.pixX0 + gitter.pixWidth; p1.Y = ymin; p2.X = gitter.pixX0 + gitter.pixWidth; p2.Y = gitter.pixY0; dc.DrawLine(penBlack, p1, p2); drawTextZentr(dc, 11, gitter.pixX0 + gitter.pixWidth, yfont, getNumberWithFormat(x, xAchse.nachkommastellen)); } else { p1.X = ix; p1.Y = ymin; p2.X = ix; p2.Y = ymax; dc.DrawLine(penBlack, p1, p2); drawTextZentr(dc, 11, ix, yfont, getNumberWithFormat(x, xAchse.nachkommastellen)); } x += xAchse.xsw; erster = false; } } private String getNumberWithFormat(double x, int nachkommastellen) { switch (nachkommastellen) { case 0: return x.ToString("0"); case 1: return x.ToString("0.0"); case 2: return x.ToString("0.00"); case 3: return x.ToString("0.000"); case 4: return x.ToString("0.0000"); case 5: return x.ToString("0.00000"); default: return x.ToString("0.00000"); } } private void drawTextZentr(DrawingContext dc, int fontsize, double x, double y, String value) { if (value.Length == 0) { return; } else { FormattedText formattedText = new FormattedText(value, CultureInfo.GetCultureInfo("DE-de"), FlowDirection.LeftToRight, new Typeface("Verdana"), fontsize, new SolidColorBrush(Colors.Black)); double wx = formattedText.Width; dc.DrawText(formattedText, new Point(x - (wx * 0.5), y - fontheight)); } } // drawTextZentr private void drawTextZentrY(DrawingContext dc, double x, double y, String value) { if (value.Length == 0) { return; } else { FormattedText formattedText = new FormattedText(value, CultureInfo.GetCultureInfo("DE-de"), FlowDirection.LeftToRight, new Typeface("Verdana"), 11, new SolidColorBrush(Colors.Black)); double wx = formattedText.Width*0.5; double gx = -wx - gitter.MaxY*0.5; // +wx; double gy = 5; // gitter.MaxX - y; RotateTransform RT = new RotateTransform(270, 0, 0); dc.PushTransform(RT); dc.DrawText(formattedText, new Point(gx,gy)); //dc.DrawLine(penBlack, new Point(0, 0), new Point(-100, -100)); //dc.DrawLine(penBlack, new Point(0, 0), new Point(-100, 100)); dc.Pop(); } } // drawTextZentrY private void drawTextRight(DrawingContext dc, double x, double y, String value) { if (value.Length == 0) { return; } else { FormattedText formattedText = new FormattedText(value, CultureInfo.GetCultureInfo("DE-de"), FlowDirection.LeftToRight, new Typeface("Verdana"), 11, new SolidColorBrush(Colors.Black)); double wx = formattedText.Width; dc.DrawText(formattedText, new Point(x-wx, y )); } } // drawTextLeft internal void drawYLines(DrawingContext dc) { int i = 0; double ylen = 5; double pos, iy, iyy; bool erster = true; bool letzter = false; double y = yAchse.xa; double yee = yAchse.xe + yAchse.xsw * 0.01; double xmin = gitter.pixX0 - ylen; double xmax = gitter.pixX0 + gitter.pixWidth; double xfont = gitter.pixX0 - ylen-3; // fontheight; // -ylen double fonthalbe = fontheight *0.5; while (y <= yee) { i++; pos = GOWandleY(y); iy = gitter.MaxY - (gitter.pixY0 + pos); letzter = (y + yAchse.xsw) > yee; if (erster) { iyy = gitter.MaxY - gitter.pixY0; p1.X = gitter.pixX0 - ylen; p1.Y = iyy; p2.X = gitter.pixX0; p2.Y = iyy; dc.DrawLine(penBlack, p1, p2); } else if (letzter) { iyy = gitter.MaxY - (gitter.pixY0 + gitter.pixHeight); p1.X = gitter.pixX0 - ylen; p1.Y = iyy; p2.X = gitter.pixX0; p2.Y = iyy; dc.DrawLine(penBlack, p1, p2); } else { p1.X = xmin; p1.Y = iy; p2.X = xmax; p2.Y = iy; dc.DrawLine(penBlack, p1, p2); } drawTextRight(dc, xfont, iy - fonthalbe, getNumberWithFormat(y, yAchse.nachkommastellen)); y += yAchse.xsw; erster = false; } } internal void drawCoords(DrawingContext dc) { if (coords == null) return; int n = coords.Count; double ix1, iy1, ix2, iy2; PointXY cp1, cp2; for (int i = 0; i < n - 1; i++) { cp1 = coords[i]; cp2 = coords[i+1]; ix1 = gitter.pixX0 + GOWandleX(cp1.x); iy1 = gitter.pixY0 + GOWandleY(cp1.y); ix2 = gitter.pixX0 + GOWandleX(cp2.x); iy2 = gitter.pixY0 + GOWandleY(cp2.y); p1.X = ix1; p1.Y = gitter.MaxY - iy1; p2.X = ix2; p2.Y = gitter.MaxY - iy2; dc.DrawLine( penBlue, p1, p2); } } private double GOWandleX(double x) { double r, d1, result; result = 0; if (xAchse.xsw > 0) { d1 = faktorGowXPlus * (x - xAchse.xa); if (d1 < 0) d1 = 0; result = d1; } else { d1 = faktorGowXMinus * (xAchse.xa - x); if (d1 < 0) d1 = 0; result = d1; } return (int)result; } // GOWandlex private double GOWandleY(double y) { double r, d1, result; result = 0; if (yAchse.xsw > 0) { d1 = faktorGowYPlus * (y - yAchse.xa); if (d1 < 0) d1 = 0; result = d1; } else { r = faktorGowYMinus * (yAchse.xa - y); d1 = r + gitter.pixY0; if (d1 < 0) d1 = 0; result = d1; } return (int)result; } // GOWandley } // Graphic class Gitter { public double MaxY = 0; public double MaxX = 0; public double pixWidth = 0; public double pixHeight = 0; public double pixX0; // Koordinatenursprung public double pixY0; public double pixTop; // gitter.pixY0-gitter.pixHeight public String title=""; } public class PointXY { public double x=0; public double y=0; public PointXY(double x, double y) { this.x = x; this.y = y; } } class Achse { public double xa; public double xsw; public double xe; public int nachkommastellen; public int ticks; public String bezeichnung = ""; public Achse() { xa = 0.0; xsw = 1; xe = 10; nachkommastellen = 0; ticks = 4; } public void setNachkommastellen() { int nk = -1; double dummy; String str; String format="0."; for (int i = 0; i < 5; i++) { str = xsw.ToString(format); dummy = Double.Parse(str); if (xsw == dummy) { nk = i; break; } format += "0"; } if (nk == -1) nachkommastellen = 5; else nachkommastellen = nk; } } // Achse }