/// <summary> /// Paints the control. /// </summary> /// <param name="g">The Graphics object to paint to.</param> public void PaintGraph(Graphics g) { double x, y, z; float X, Y, Z, d; int n; Rectangle frame, bounds = this.Bounds; SizeF size; Region clip, frameclip, boundsclip; double x0 = Model.x0, y0 = Model.y0, z0 = Model.z0, x1 = Model.x1, y1 = Model.y1, z1 = Model.z1, rx = Model.rx, ry = Model.ry, rz = Model.rz, srx = rx / 5, sry = ry / 5, srz = rz / 5; CalcFrame(g, bounds); g.TranslateTransform(fx, fy, MatrixOrder.Append); frame = new Rectangle(0, 0, fw + 1, fh + 1); bounds = new Rectangle(-fx, -fy, bounds.Width, bounds.Height); clip = g.Clip.Clone(); frameclip = clip.Clone(); boundsclip = clip.Clone(); frameclip.Intersect(frame); boundsclip.Intersect(bounds); double dx = (x1 - x0) / fw; double dy = (y1 - y0) / fh; double dz = (z1 - z0) / fh; pen.DashStyle = DashStyle.Solid; pen.Width = 1; g.SetClip(frameclip, CombineMode.Replace); //calculate functions Calc.Start(frame); if (!AsyncDraw) { while (!Calc.done) { } } //draw items for (int i = 0; i < Model.Items.Count; i++) { Model.Items[i].Draw(g, Calc); } // draw selection if (sw != 0 && sh != 0) { pen.Color = Color.White; g.DrawRectangle(pen, Math.Min(sx - fx, sx + sw - fx), Math.Min(sy - fy, sy + sh - fy), Math.Abs(sw), Math.Abs(sh)); pen.DashPattern = new float[2] { 3, 3 }; pen.DashStyle = DashStyle.Custom; pen.Color = Color.Black; g.DrawRectangle(pen, Math.Min(sx - fx, sx + sw - fx), Math.Min(sy - fy, sy + sh - fy), Math.Abs(sw), Math.Abs(sh)); pen.DashStyle = DashStyle.Solid; } // draw raster pen.Color = Model.ScaleColor; pen.Width = Model.ScaleLineWidth; brush.Color = Model.ScaleColor; g.DrawRectangle(pen, 0, 0, fw, fh); string label; x = Math.Floor(x0 / rx) * rx + rx; n = -4; while (x + srx * n < x1) { X = (float)((x + srx * n - x0) / dx); if (Model.xGrid && n % 5 == 0 && !((int)(-x0 / dx + 0.5) == (int)(X + 0.5F) && Model.yAxis)) { pen.Color = Color.FromArgb(64, Model.ScaleColor); g.DrawLine(pen, X, 0, X, fh); pen.Color = Model.ScaleColor; } if (Model.xRaster && !((int)(-x0 / dx + 0.5) == (int)(X + 0.5F) && Model.yAxis)) { if (n % 5 == 0) { d = fd; } else { d = fd / 2; } g.DrawLine(pen, X, 0, X, d); g.DrawLine(pen, X, fh - d, X, fh); } if (Model.xScale && (n % 5 == 0)) { if ((int)(-x0 / dx + 0.5) == (int)(X + 0.5F)) { label = "0"; } else { label = (x + srx * n).ToString(GraphModel.NumberFormat(Model.xDigits, Model.xNumberStyle)); } size = g.MeasureString(label, Model.ScaleFont); g.SetClip(boundsclip, CombineMode.Replace); if (Model.Border) { g.DrawString(label, Model.ScaleFont, brush, new PointF(X - size.Width / 2, fh + D / 2)); } else { g.DrawString(label, Model.ScaleFont, brush, new PointF(X - size.Width / 2, fh - 2 * fd - D / 2)); } g.SetClip(frameclip, CombineMode.Replace); } if (yAxis && (int)(-x0 / dx + 0.5) == (int)(X + 0.5F)) { g.DrawLine(pen, X, 0, X, fh); } n++; } y = Math.Floor(y0 / ry) * ry + ry; n = -4; while (y + sry * n < y1) { Y = fh - 1 - (float)((y + sry * n - y0) / dy); if (Model.yGrid && n % 5 == 0 && !((int)(fh - 1 - (float)(-y0 / dy) + 0.5F) == (int)(Y + 0.5F) && xAxis)) { pen.Color = Color.FromArgb(64, Model.ScaleColor); g.DrawLine(pen, 0, Y, fw, Y); pen.Color = Model.ScaleColor; } if (Model.yRaster && !((int)(fh - 1 - (float)(-y0 / dy) + 0.5F) == (int)(Y + 0.5F) && xAxis)) { if (n % 5 == 0) { d = fd; } else { d = fd / 2; } g.DrawLine(pen, 0, Y, d, Y); g.DrawLine(pen, fw - d, Y, fw, Y); } if (Model.yScale && (n % 5 == 0)) { if ((int)(fh - 1 - (float)(-y0 / dy) + 0.5F) == (int)(Y + 0.5F)) { label = "0"; } else { label = (y + sry * n).ToString(GraphModel.NumberFormat(Model.yDigits, Model.yNumberStyle)); } size = g.MeasureString(label, Model.ScaleFont); g.SetClip(boundsclip, CombineMode.Replace); if (Model.Border) { g.DrawString(label, Model.ScaleFont, brush, new PointF(-size.Width - D / 2, Y - fd / 2)); } else { g.DrawString(label, Model.ScaleFont, brush, new PointF(D / 2 + fd, Y - fd / 2)); } g.SetClip(frameclip, CombineMode.Replace); } if (xAxis && (int)(fh - 1 - (float)(-y0 / dy) + 0.5F) == (int)(Y + 0.5F)) { g.DrawLine(pen, 0, Y, fw, Y); } n++; } //draw z-Scale if (Model.zScale && GetZBitmap()) { g.SetClip(boundsclip, CombineMode.Replace); g.DrawImage(zscale.img, fw + fd, 0, fd, fh); g.DrawRectangle(pen, fw + fd, 0, fd, fh); z = Math.Floor(z0 / rz) * rz + rz; n = -4; while (z + srz * n < z1) { Z = fh - 1 - (float)((z + srz * n - z0) / dz); if (n % 5 == 0) { d = fd; } else { d = fd / 2; } g.DrawLine(pen, fw + 2 * fd, Z, fw + 2 * fd + d, Z); if (n % 5 == 0) { if ((int)(fh - 1 - (float)(-z0 / dz) + 0.5F) == (int)(Z + 0.5F)) { label = "0"; } else { label = (z + srz * n).ToString(GraphModel.NumberFormat(Model.zDigits, Model.zNumberStyle)); } //size = g.MeasureString(label, Model.ScaleFont); g.DrawString(label, Model.ScaleFont, brush, new PointF(fw + D / 2 + 3 * fd, Z - fd / 2)); } n++; } } //draw legend if (Model.Legend) { float lw = 0; int m = 0; pen.Color = Model.ScaleColor; for (n = 0; n < Model.Items.Count; n++) { if (Model.Items[n] is Function1D || (Model.Items[n] is DataItem && ((DataItem)Model.Items[n]).lines)) { m++; size = g.MeasureString(Model.Items[n].name, Model.ScaleFont); lw = Math.Max(lw, size.Width); } } int w = (int)(lw + 0.5) + (7 * fd) / 2, h = fd * m + D; if (Model.LegendBorder) { brush.Color = Color.White; g.FillRectangle(brush, fw - 2 * fd - w, fy + 2 * fd, w, h); g.DrawRectangle(pen, fw - 2 * fd - w, fy + 2 * fd, w, h); } m = 0; for (n = 0; n < Model.Items.Count; n++) { if (Model.Items[n] is Function1D || (Model.Items[n] is DataItem && ((DataItem)Model.Items[n]).lines)) { brush.Color = Model.ScaleColor; g.DrawString(Model.Items[n].name, Model.ScaleFont, brush, fw + fd - w, fy + 2 * fd + D / 2 + m * fd); pen.DashStyle = Model.Items[n].lineStyle; pen.Width = Model.Items[n].lineWidth; g.DrawLine(pen, fw - w - (3 * fd) / 2, fy + 3 * fd + D / 2 + m * fd - fd / 2, fw - w + fd / 2, fy + 3 * fd + D / 2 + m * fd - fd / 2); m++; } } } //draw status message if (!Calc.done) { brush.Color = Color.Red; g.DrawString("calculating...", Model.ScaleFont, brush, bounds.Width / 2, bounds.Height / 2); } else { if (Bar != null) { lock (Bar) { Bar.Value = 0; } } } //reset Graphics g.ResetTransform(); g.SetClip(clip, CombineMode.Replace); }
/// <summary> /// Calculates the bounds of the plotting area inside the control. /// </summary> /// <param name="g">A Graphics object.</param> /// <param name="bounds">The bounds of the entire control.</param> private void CalcFrame(Graphics g, Rectangle bounds) { int w = 0, h = 0, ww, wz = 0, n, W, H; double y0 = Model.y0, y1 = Model.y1, x0 = Model.x0, x1 = Model.x1, z0 = Model.z0, z1 = Model.z1, rx = Model.rx, ry = Model.ry, rz = Model.rz, dy = (y1 - y0) / bounds.Height, dz = (z1 - z0) / bounds.Height, x, y, z; SizeF size; string label; float Y, Z; y = 0.5; size = g.MeasureString(y.ToString(GraphModel.NumberFormat(Model.xDigits, Model.xNumberStyle)), Model.ScaleFont); fd = (int)(size.Height + 0.5F); if (Model.Border) { if (Model.yScale) { y = Math.Floor(y0 / ry) * ry; n = 1; while ((y + n * ry) < y1) { Y = bounds.Height - 1 - (float)((y + n * ry - y0) / dy); if ((int)(bounds.Height - 1 - (float)(-y0 / dy) + 0.5F) == (int)(Y + 0.5F)) { label = "0"; } else { label = (y + n * ry).ToString(GraphModel.NumberFormat(Model.yDigits, Model.yNumberStyle)); } size = g.MeasureString(label, Model.ScaleFont); w = Math.Max(w, (int)(size.Width + 0.5)); n++; } } else { w = 0; } if (Model.xScale) { h = fd; x = Math.Floor(x1 / rx) * rx; label = x.ToString(GraphModel.NumberFormat(Model.xDigits, Model.xNumberStyle)); size = g.MeasureString(label, Model.ScaleFont); ww = (int)(size.Width / 2 + 1); } else { ww = 0; } if (Model.zScale) { Function2D f = null; for (int i = 0; i < Model.Items.Count; i++) { if (Model.Items[i] is Function2D) { f = (Function2D)Model.Items[i]; } } if (f != null) { z = Math.Floor(z0 / rz) * rz; n = 1; while ((z + n * rz) < z1) { Z = bounds.Height - 1 - (float)((z + n * rz - z0) / dz); if ((int)(bounds.Height - 1 - (float)(-z0 / dz) + 0.5F) == (int)(Z + 0.5F)) { label = "0"; } else { label = (z + n * rz).ToString(GraphModel.NumberFormat(Model.zDigits, Model.zNumberStyle)); } size = g.MeasureString(label, Model.ScaleFont); wz = Math.Max(wz, (int)(size.Width + 0.5)); n++; } wz += 3 * fd + D; } else { wz = 0; } } else { wz = 0; } fx = w + D; fy = D / 2 + fd / 2; W = bounds.Width - w - (3 * D) / 2 - ww - wz; H = bounds.Height - h - fd / 2 - (3 * D) / 2; if (W != fw && FixYtoX) { fw = W; fh = H; Model.SetRange(x0, x1, y0, y1, fw, fh); } fw = W; fh = H; } else { fx = bounds.X; fy = bounds.Y; fw = bounds.Width - 1; fh = bounds.Height - 2; } }