예제 #1
0
        /*
         * /// <summary>
         * /// Represents a raster line
         * /// </summary>
         * public class Line {
         *      /// <summary>
         *      /// The x-coordinate of the line
         *      /// </summary>
         *      public double x;
         *      /// <summary>
         *      /// Indicates if the line is a big or small raster line
         *      /// </summary>
         *      public bool big = false;
         * }
         * /// <summary>
         * /// Represents all raster lines of a scale
         * /// </summary>
         * public class ScaleLines: List<Line> { }
         * /// <summary>
         * /// Draws the scale and raster lines specified in lines.
         * /// </summary>
         */ /*
         * public void DrawScaleLines(Graphics g, PlotModel Model, Scale scale, bool draw,  PointF[] v, ref Norms norms, ,
         *      ScaleLines lines) {
         *
         *      Norms normsText = new Norms();
         *      Norm yNorm;
         *
         *      // init matrices
         *      Matrix id, T0, T, Tprod, Trot, Tinv;
         *
         *      id = new Matrix();
         *      T0 = g.Transform.Clone();
         *      RectangleF Tframe = Bounds;
         *      T = new Matrix(Tframe, v);
         *      norms.T = normsText.T = T;
         *      Tinv = T.Clone();
         *      Tinv.Invert();
         *      Tprod = T0.Clone();
         *      Tprod.Multiply(T);
         *      Trot = new Matrix();
         *      if (scale.unitAngleRelative) Trot.Rotate(scale.unitAngle - Angle(Diff(v[1], v[0])));
         *      else Trot.Rotate(scale.unitAngle);
         *      g.Transform = Tprod;
         *
         *      PointF[] p = new PointF[4];
         *      double x0 = scale.lower, x1 = scale.upper;
         *      if (x0 > x1) {
         *              double t = x0; x0 = x1; x1 = t;
         *      }
         *      // double d = (x1 - x0)/W;
         *      // double x = Math.Floor(x0/scale.r)*scale.r + scale.r;
         *      double sr = scale.r/5;
         *      float Y, X0 = scale.DeviceCoordinate(0, Bounds);
         *      SizeF size = g.MeasureString("0.5", Model.ScaleFont);
         *      float s, s0 = Math.Max(1, (int)(size.Height + 0.5F));
         *      Pen pen = new Pen(Model.ScaleColor, Model.ScaleLineWidth); // the pen used for drawing
         *      SolidBrush brush = new SolidBrush(Model.ScaleColor);
         *      SolidBrush background = new SolidBrush(Model.BackgroundColor);
         *      foreach (Line l in lines) { // interate over raster
         *              if (x0 <= l.x && l.x <= x1) {
         *                      float X = scale.DeviceCoordinate(l.x, Bounds);
         *                      bool isX0 = Math.Round(X0) == Math.Round(X);
         *                      if (draw && (!isX0 || !scale.axis)) { // X is not axis
         *                              if (scale.grid && l.big) { // draw grid
         *                                      pen.Color = Color.FromArgb(255, Model.ScaleColor);
         *                                      g.DrawLine(pen, X, 0, X, Bounds.Height);
         *                                      pen.Color = Model.ScaleColor;
         *                              }
         *                              if (scale.raster) { // draw raster
         *                                      if (l.big) s = s0;
         *                                      else s = s0/2;
         *                                      if (scale.rasterOutside) { // draw raster on outside
         *                                              if (scale.raster) g.DrawLine(pen, X, -s, X, 0);
         *                                              if (scale.oppositeRaster) g.DrawLine(pen, X, Bounds.Height + s, X, H);
         *                                      } else { // draw raster on inside
         *                                              if (scale.raster) g.DrawLine(pen, X, 0, X, s);
         *                                              if (scale.oppositeRaster) g.DrawLine(pen, X, H - s, X, H);
         *                                      }
         *                              }
         *                      } else if (draw && scale.axis) { // draw 0-axis.
         *                              g.DrawLine(pen, X, 0, X, H);
         *                      }
         *
         *                      if (scale.scale && l.big) { // draw scale text
         *                              string label;
         *                              if (isX0) label = "0";
         *                              else label = scale.UnitToString(l.x);
         *
         *                              if (scale.scaleOutside != scale.rasterOutside) s = 0.5F*s0; // distance from line to scale
         *                              else s = 1.5F*s0;
         *                              if (scale.scaleOutside) { // draw scale outside the box
         *                                      Y = -s;
         *                                      yNorm = Norm.Max;
         *                              } else { // draw scale inside the box
         *                                      Y = s;
         *                                      yNorm = Norm.Min;
         *                              }
         *                              g.Transform = T0; // reset transformation
         *                              DrawText(g, label, draw, Model.ScaleFont, brush, background, X, Norm.Average, Y, yNorm, id, T, Tinv, ref p, ref normsText);
         *                              g.Transform = Tprod;
         *                      }
         *              }
         *      }
         *
         *      // draw units
         *      g.Transform = T0;
         *
         *      size = g.MeasureString(scale.unit, Model.UnitsFont);
         *      s0 = size.Height/2;
         *
         *      if (scale.scaleOutside) {
         *              Y = normsText.min.Y - s0; yNorm = Norm.Max; // draw the units below the scale
         *      } else {
         *              Y = normsText.max.Y + s0; yNorm = Norm.Min; // draw the units above the scale
         *      }
         *      DrawText(g, scale.unit, draw, Model.UnitsFont, brush, background, W/2, Norm.Average, Y, yNorm, Trot, T, Tinv, ref p, ref norms);
         *      norms += normsText;
         * }
         */

        /// <summary>
        /// Draws a <see cref="Scale">Scale</see>. The point-array v is an array of 3 points that denote the orientation
        /// of the scale. The primary scale is drawn from v[0] -> v[1], the opposite scale is drawn from
        /// v[0] + v[2] -> v[1] + v[2].
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> object to draw to.</param>
        /// <param name="v">The orientation of the scale</param>
        /// <param name="Model">The <see cref="PlotModel"/> of the Plot to draw</param>
        /// <param name="scale">The scale to draw</param>
        /// <param name="draw">If false, the scale is not drawn but it's dimensions are added to norms.</param>
        /// <param name="norms">The <see cref="Norms"/> the extension-points of the scale will be added to.</param>
        public static void DrawScale(Graphics g, PointF[] v, PlotModel Model, Scale scale, bool draw, ref Norms norms)
        {
            //TODO Inverse Scales (where scale.lower > scale.upper)
            //TODO logscales

            const int  GridAlpha = 64;            // the alpha-color value of the grid lines.
            float      X, X0, Y, W, H, s, s0;
            double     x, sr, t, x0, x1;
            Matrix     id, T0, T, Tprod, Trot, Tinv;
            int        n, Width;
            Pen        pen        = new Pen(Model.ScaleColor, Model.ScaleLineWidth); // the pen used for drawing
            SolidBrush brush      = new SolidBrush(Model.ScaleColor);
            SolidBrush background = new SolidBrush(Model.BackgroundColor);
            string     label;
            RectangleF Tframe;
            PointF     d1, d2, d3;
            bool       isX0;
            Norm       yNorm;

            PointF[] p = new PointF[4];
            SizeF    size;
            Norms    normsText = new Norms();

            x0 = scale.lower; x1 = scale.upper;
            if (x0 > x1)                // lower bound is greater than upper bound. Exchange bounds.
            {
                t = x0; x0 = x1; x1 = t;
            }
            d1 = Diff(v[1], v[0]);
            d2 = Diff(v[2], v[0]);
            d3 = Diff(v[1], v[2]);
            if (v[0] == v[1] || v[0] == v[2] || v[1] == v[2])
            {
                return;
            }

            W = (float)Math.Sqrt(d1.X * d1.X + d1.Y * d1.Y);
            H = (float)Math.Sqrt(d2.X * d2.X + d2.Y * d2.Y);
            W = Math.Max(W, 1);
            H = Math.Max(H, 1);

            Width  = (int)(W + 1.5);
            Tframe = new RectangleF(0, 0, W, H);

            size = g.MeasureString("0.5", Model.ScaleFont);
            s0   = Math.Max(1, size.Height);

            // init matrices
            id      = new Matrix();
            T0      = g.Transform.Clone();
            T       = new Matrix(Tframe, v);
            norms.T = normsText.T = T;
            Tinv    = T.Clone();
            Tinv.Invert();
            Tprod = T0.Clone();
            Tprod.Multiply(T);
            Trot = new Matrix();
            if (scale.unitAngleRelative)
            {
                Trot.Rotate(scale.unitAngle - Angle(Diff(v[1], v[0])));
            }
            else
            {
                Trot.Rotate(scale.unitAngle);
            }
            g.Transform = Tprod;

            p[0] = new PointF(0, 0); p[1] = new PointF(W, 0); p[2] = new PointF(W, H); p[3] = new PointF(0, H);
            norms.Add(p);

            if (draw)                   // draw the solid lines of the scale and opposite scale
            {
                if (scale.line)
                {
                    g.DrawLine(pen, p[0], p[1]);
                }
                if (scale.oppositeLine)
                {
                    g.DrawLine(pen, p[3], p[2]);
                }
            }

            // add the minimum rectangle to the normsText. (So that the units will be in the right position, even if there is no scale.)
            if (scale.scaleOutside != scale.rasterOutside)
            {
                s = 0.5F * s0;
            }
            else
            {
                s = 1.5F * s0;
            }
            if (scale.scaleOutside)
            {
                s = -s;
            }
            Y    = s;
            p[0] = new PointF(0, Y); p[1] = new PointF(W, Y); p[2] = new PointF(W, Y); p[3] = new PointF(0, Y);
            normsText.Add(p);

            // draw scale
            if (!scale.logarithmic)
            {
                sr = scale.r;
                x  = Math.Floor(x0 / sr) * sr + sr;
                sr = sr / 5;
                X0 = scale.DeviceCoordinate(0, (int)(W + 0.5F));
                n  = -4;
                // interate over raster
                while ((sr > 0 && x + sr * n < x0) || (sr < 0 && x + sr * n > x0))
                {
                    n++;
                }
                while ((sr > 0 && x + sr * n < x1) || (sr < 0 && x + sr * n > x1))
                {
                    X = scale.DeviceCoordinate(x + sr * n, (int)(W + 0.5F));
                    // X = (float)((x + sr*n - x0)/d);
                    isX0 = Math.Round(X0) == Math.Round(X);
                    if (draw && (!isX0 || !scale.axis))                       // X is not axis
                    {
                        if (scale.grid && n % 5 == 0)                         // draw grid
                        {
                            pen.Color = Color.FromArgb(GridAlpha, Model.ScaleColor);
                            g.DrawLine(pen, X, 0, X, H);
                            pen.Color = Model.ScaleColor;
                        }
                        if (scale.raster)                           // draw raster
                        {
                            if (n % 5 == 0)
                            {
                                s = s0;
                            }
                            else
                            {
                                s = s0 / 2;
                            }
                            if (scale.rasterOutside)                               // draw raster on outside
                            {
                                if (scale.raster)
                                {
                                    g.DrawLine(pen, X, -s, X, 0);
                                }
                                if (scale.oppositeRaster)
                                {
                                    g.DrawLine(pen, X, H + s, X, H);
                                }
                            }
                            else                                 // draw raster on inside
                            {
                                if (scale.raster)
                                {
                                    g.DrawLine(pen, X, 0, X, s);
                                }
                                if (scale.oppositeRaster)
                                {
                                    g.DrawLine(pen, X, H - s, X, H);
                                }
                            }
                        }
                    }
                    else if (scale.axis && draw)                         // draw 0-axis.
                    {
                        g.DrawLine(pen, X, 0, X, H);
                    }

                    if (scale.scale && (n % 5 == 0))                     // draw scale
                    {
                        if (isX0)
                        {
                            label = "0";
                        }
                        else
                        {
                            label = scale.UnitToString(x + sr * n);
                        }

                        if (scale.scaleOutside != scale.rasterOutside)
                        {
                            s = 0.5F * s0;                                                                  // distance from line to scale
                        }
                        else
                        {
                            s = 1.5F * s0;
                        }
                        if (scale.scaleOutside)                           // draw scale outside the box
                        {
                            Y     = -s;
                            yNorm = Norm.Max;
                        }
                        else                             // draw scale inside the box
                        {
                            Y     = s;
                            yNorm = Norm.Min;
                        }
                        g.Transform = T0;                         // reset transformation
                        DrawText(g, label, draw, Model.ScaleFont, brush, null, X, Norm.Average, Y, yNorm, id, T, Tinv, ref p, ref normsText);
                        g.Transform = Tprod;
                    }
                    n++;
                }
            }
            else                 //scale is logarithmic
            {
                double l0 = Math.Log10(Math.Abs(x0)), l1 = Math.Log10(Math.Abs(x1));
                double ld = l1 - l0;
            }

            // draw units
            g.Transform = T0;

            size = g.MeasureString(scale.unit, Model.UnitsFont);
            s0   = size.Height / 2;

            if (scale.scaleOutside)
            {
                Y = normsText.min.Y - s0; yNorm = Norm.Max;                 // draw the units below the scale
            }
            else
            {
                Y = normsText.max.Y + s0; yNorm = Norm.Min;                 // draw the units above the scale
            }
            DrawText(g, scale.unit, draw, Model.UnitsFont, brush, null, W / 2, Norm.Average, Y, yNorm, Trot, T, Tinv, ref p, ref norms);
            norms += normsText;
        }