Ejemplo n.º 1
0
        public override int GetHashCode()
        {
            int hash = 1;

            if (ActionId != 0)
            {
                hash ^= ActionId.GetHashCode();
            }
            if (Num != 0)
            {
                hash ^= Num.GetHashCode();
            }
            if (T0 != 0L)
            {
                hash ^= T0.GetHashCode();
            }
            if (T1 != 0L)
            {
                hash ^= T1.GetHashCode();
            }
            if (T2 != 0L)
            {
                hash ^= T2.GetHashCode();
            }
            if (T3 != 0L)
            {
                hash ^= T3.GetHashCode();
            }
            return(hash);
        }
Ejemplo n.º 2
0
    static int Main()
    {
        bool        res   = true;
        T0 <string> t0str = new T0 <string>();

        T1 <char> t1char = new T1 <char>();

        T2 <int> t2int = new T2 <int>();

        if (t2int.Me() != 0)
        {
            res = false;
        }

        T3 <uint> t3uint = new T3 <uint>();

        if (t3uint.Home(0) != 0)
        {
            res = false;
        }

        if (res = true)
        {
            return(0);
        }

        return(1);
    }
Ejemplo n.º 3
0
 public override int GetHashCode()
 {
     unchecked
     {
         var hash0 = T0.GetHashCode();
         var hash1 = T1.GetHashCode();
         return(((hash0 << 5) + hash0) ^ hash1);
     }
 }
Ejemplo n.º 4
0
        protected void CreateTracks <T1, T0, T2>() where T1 : GenericAudioTrack, new() where T0 : GenericVideoTrack, new() where T2 : MP4TrackFormat, new()
        {
            // boolean for calling event MediaTrackLogicalBreak only once
            bool breakCalled       = false;
            GenericMediaTrack trak = null;
            T2 trackFormat;

            foreach (TrackBox trackb in mmb.TrackBoxes)
            {
                trackFormat          = new T2();
                trackFormat.TrackBox = trackb;
                switch (trackb.PayloadType)
                {
                case "samr": // 3gpp audio
                case "wma ":
                case "mp4a":
                    trak          = new T1();
                    Hints.object1 = trackb.EdtsBox;
                    break;

                case "mp4v": // 3gpp video
                case "vc-1":
                case "avc1":
                    trak = new T0();
                    IVideoTrack    vt        = trak as IVideoTrack;
                    MP4TrackFormat mp4format = trackFormat as MP4TrackFormat;
                    vt.IsAnamorphic = mp4format.IsAnamorphic;
                    Hints.object2   = trackb.EdtsBox;
                    break;

                case "mp4s":
                    break; // ignore - in the case of vc-1 and wma, these are processed in ISMVStreamReader

                default:
                    throw new Exception(string.Format("Unknown track type: {0}", trackb.PayloadType));
                }
                if (trak != null)
                {
                    trak.TrackFormat  = trackFormat;
                    trak.ParentStream = this;
                    AddTrack(trak);

                    if (!breakCalled)
                    {
                        TriggerLogicalBreak(trak);
                        breakCalled = true;
                    }
                }
            }
        }
Ejemplo n.º 5
0
 public A0(T0 value) => m_value = value;
Ejemplo n.º 6
0
        private KweeVanWoerdenResult Kwee_van_Woerden(
            long Number_Obs, double Time_First_JD,
            double[] SecondsFromTimeFirstJD, double[] Variable_Star_DN, double[] Variable_Sky_DN, double[] Comparison_Star_DN, double[] Comparison_Sky_DN,
            bool fineGranedBins)
        {
            long BASE_NUMBER = fineGranedBins ? 1000 : 100;
            /* Constant parameter */
            long Normal_Points = BASE_NUMBER + 1;                             /* Number of evenly spaced data pairs used in the analysis */
            long Normal_Point_Middle;                                         /* Index of the middle element of the normal point array */

            /* Luminosity values */
            double[] Luminosity_Ratio;                                        /* Variable luminosity divided by comparison luminosity */
            double   Luminosity_Normal_Sum;                                   /* Summation of luminosities for normal point computation */
            long     Luminosity_Normal_Count;                                 /* Counter for data points in one normal point */

            double[] Luminosity_Normal = new double[BASE_NUMBER + 2];         /* Normalized luminosities */

            /* Time values */
            double Time_Interval;                                             /* Time interval between observations */
            double Time_Start, Time_Stop;                                     /* Limits for normal points */

            double[] Time_Normal = new double[BASE_NUMBER + 2];               /* Times corresponding to normal points */

            /* Symmetry analysis */
            double Luminosity_Faintest;                                       /* Faintest normalized luminosity */
            long   Luminosity_Faintest_Index;                                 /* Index of the faintest normalized luminosity */
            long   Start_Light_Curve;                                         /* Start element of normalized light curve to analyze */
            //long         Middle_Light_Curve;                      /* Middle element of normalized light curve to analyze */
            long   Stop_Light_Curve;                                          /* Stop element of normalized light curve to analyze */
            long   Start_Sum_Squares;                                         /* Start element of the sum-of-squares array */
            long   Stop_Sum_Squares;                                          /* Stop element of the sum-of-squares array */
            double Sum_Of_Squares;                                            /* Sum of squares across a time of symmetry */

            long[]   Sum_Of_Squares_Count = new long[BASE_NUMBER + 2];        /* Number of squares accumulated */
            double[] Sum_Of_Squares_Mean  = new double[BASE_NUMBER + 2];      /* Sum of squares divided by count */
            long     Sum_Of_Squares_Smallest_Index;                           /* Index of the smallest sum of squares */
            double   Sum_Of_Squares_Smallest;                                 /* Smallest sum of squares */

            /* Time of minimum and uncertainty */
            double[] Quad = new double[4];                                    /* Inputs to the quadratic equation taken from the sums of squares */
            double   A, B, C;                                                 /* Intermediate values for quadratic equation */
            double   T0;                                                      /* Time of symmetry */
            double   T0_Uncertainty;                                          /* Time of symmetry uncertainty */
            //double       Time_Of_Minimum;                         /* Time of minimum light */
            //double       Time_Of_Minimum_Uncertainty;             /* Time of minimum light uncertainty */

            /* Loop indices */
            long i, j;                                                        /* Loop indices */

            var rv = new KweeVanWoerdenResult()
            {
                NumberObservations = Number_Obs
            };

            rv.Observations_File.Add("                Time     Luminosity_Ratio     Variable_Star_DN      Variable_Sky_DN   Comparison_Star_DN    Comparison_Sky_DN");
            rv.Normals_File.Add("                Time    Luminosity_Ratio");


            double[] Time = new double[Number_Obs];
            for (int k = 0; k < Number_Obs; k++)
            {
                Time[k] = SecondsFromTimeFirstJD[k] / 86400.0;
            }

            Luminosity_Ratio = new double[Number_Obs];
            /* Determine luminosity ratios */
            for (i = 0; i < Number_Obs; i++)
            {
                Luminosity_Ratio[i] = (Variable_Star_DN[i] - Variable_Sky_DN[i]) / (Comparison_Star_DN[i] - Comparison_Sky_DN[i]);

                rv.Observations_File.Add(
                    Time[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Luminosity_Ratio[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Variable_Star_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Variable_Sky_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Comparison_Star_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Comparison_Sky_DN[i].ToString("#########0.000000").PadLeft(20));
            }

            bool hasEmptyBins = false;

            /* Compute normal point times and luminosities */
            Time_Interval = (Time[Number_Obs - 1] - Time[0]) / (float)Normal_Points;
            for (i = 0; i < Normal_Points; i++)
            {
                Time_Start              = Time[0] + i * Time_Interval;
                Time_Normal[i]          = Time_Start + Time_Interval / 2.0;
                Time_Stop               = Time_Start + Time_Interval;
                Luminosity_Normal_Sum   = 0.0;
                Luminosity_Normal_Count = 0;
                for (j = 0; j < Number_Obs; j++)
                {
                    if ((Time[j] >= Time_Start) && (Time[j] < Time_Stop))
                    {
                        Luminosity_Normal_Sum   = Luminosity_Normal_Sum + Luminosity_Ratio[j];
                        Luminosity_Normal_Count = Luminosity_Normal_Count + 1;
                    }
                }

                if (Luminosity_Normal_Count > 0)
                {
                    Luminosity_Normal[i] = Luminosity_Normal_Sum / (float)Luminosity_Normal_Count;
                    rv.Normals_File.Add(Time_Normal[i].ToString("#########0.000000").PadLeft(20) + " " + Luminosity_Normal[i].ToString("#########0.000000").PadLeft(20));
                }
                else
                {
                    hasEmptyBins         = true;
                    Luminosity_Normal[i] = double.NaN;
                }
            }

            if (hasEmptyBins)
            {
                for (i = 0; i < Normal_Points; i++)
                {
                    bool isEmptyBin = double.IsNaN(Luminosity_Normal[i]);
                    if (isEmptyBin)
                    {
                        double?prevBin2  = i <= 1 ? (double?)null : Luminosity_Normal[i - 2];
                        double?prevBin   = i == 0 ? (double?)null : Luminosity_Normal[i - 1];
                        var    emptyBins = new List <double>();
                        long   k         = i;
                        while (k < Normal_Points && double.IsNaN(Luminosity_Normal[k]))
                        {
                            k++;
                            emptyBins.Add(double.NaN);
                        }
                        double?nextBin  = k == Normal_Points ? (double?)null : Luminosity_Normal[k];
                        double?nextBin2 = k + 1 < Normal_Points || k + 1 >= Luminosity_Normal.Length ? (double?)null : Luminosity_Normal[k + 1];

                        if ((prevBin == null && nextBin2 == null) || (prevBin2 == null && nextBin == null))
                        {
                            rv.ErrorMessage = "Too many empty bins!";
                            return(rv);
                        }

                        double step = 0;
                        if (prevBin == null)
                        {
                            step = nextBin2.Value - nextBin.Value;
                        }
                        else if (nextBin == null)
                        {
                            step = prevBin.Value - prevBin2.Value;
                        }
                        else
                        {
                            step = (nextBin.Value - prevBin.Value) / (1 + emptyBins.Count);
                        }


                        for (int l = 0; l < emptyBins.Count; l++)
                        {
                            Luminosity_Normal[i + l] = prevBin.Value + l * step;
                        }
                    }
                }
            }

            rv.Buckets.Clear();
            rv.Buckets.AddRange(Luminosity_Normal);

            /* Locate the faintest luminosity */
            Luminosity_Faintest       = 1000000000.0;
            Luminosity_Faintest_Index = 0;
            for (i = 0; i < Normal_Points; i++)
            {
                if (Luminosity_Normal[i] < Luminosity_Faintest)
                {
                    Luminosity_Faintest_Index = i;
                    Luminosity_Faintest       = Luminosity_Normal[i];
                }
            }

            /* Set the limits of the light curve to be symmetrical around the faintest luminosity */
            Start_Light_Curve   = 0;
            Stop_Light_Curve    = Normal_Points - 1;
            Normal_Point_Middle = Normal_Points / 2;
            if (Luminosity_Faintest_Index < Normal_Point_Middle)
            {
                Stop_Light_Curve = 2 * Luminosity_Faintest_Index;
            }
            if (Luminosity_Faintest_Index > Normal_Point_Middle)
            {
                Start_Light_Curve = 2 * Luminosity_Faintest_Index - Normal_Points + 1;
            }
            rv.IncludedObservations = 100 * (Stop_Light_Curve - Start_Light_Curve - 2) / BASE_NUMBER;

            rv.Start_Light_Curve = Start_Light_Curve;
            rv.Stop_Light_Curve  = Stop_Light_Curve;

            double startTime  = Time[0] + Start_Light_Curve * Time_Interval;
            double stopTime   = Time[0] + (Stop_Light_Curve + 1) * Time_Interval;
            long   startIndex = 0;
            long   stopIndex  = Number_Obs - 1;

            for (int k = 0; k < Number_Obs; k++)
            {
                if (Start_Light_Curve > 0 && Time[k] <= startTime)
                {
                    startIndex = k + 1;
                }
                if (Stop_Light_Curve < Number_Obs - 1 && k > 1 && Time[k] > stopTime && Time[k - 1] < stopTime)
                {
                    stopIndex = k - 1;
                }
            }
            rv.Start_Light_Curve_Obs_Index = startIndex;
            rv.Stop_Light_Curve_Obs_Index  = stopIndex;

            /* Compute the normalized sums of squares of luminosity differences across an array of times */
            Start_Sum_Squares = Start_Light_Curve + 1;
            Stop_Sum_Squares  = Stop_Light_Curve - 1;
            for (i = Start_Sum_Squares; i <= Stop_Sum_Squares; i++)
            {
                Sum_Of_Squares          = 0.0;
                Sum_Of_Squares_Count[i] = 0;

                for (j = 0; j < Normal_Points; j++)
                {
                    if (i - j >= 0 && i + j < Normal_Points)
                    {
                        Sum_Of_Squares          = Sum_Of_Squares + Math.Pow(Luminosity_Normal[i - j] - Luminosity_Normal[i + j], 2);
                        Sum_Of_Squares_Count[i] = Sum_Of_Squares_Count[i] + 1;
                    }
                }

                Sum_Of_Squares_Mean[i] = Sum_Of_Squares / (float)Sum_Of_Squares_Count[i];
            }

            rv.Sum_Of_Squares_Count.Clear();
            rv.Sum_Of_Squares_Count.AddRange(Sum_Of_Squares_Count);
            rv.Sum_Of_Squares_Mean.Clear();
            rv.Sum_Of_Squares_Mean.AddRange(Sum_Of_Squares_Mean);

            /* Find the smallest normalized sum of squares */
            Sum_Of_Squares_Smallest       = 1000000000;
            Sum_Of_Squares_Smallest_Index = 0;
            for (i = Start_Sum_Squares; i <= Stop_Sum_Squares; i++)
            {
                if (Sum_Of_Squares_Mean[i] < Sum_Of_Squares_Smallest)
                {
                    /* Must also have a reasonable sample of points */
                    if (Sum_Of_Squares_Count[i] > Normal_Points / 10)
                    {
                        Sum_Of_Squares_Smallest_Index = i;
                        Sum_Of_Squares_Smallest       = Sum_Of_Squares_Mean[i];
                    }
                }
            }

            rv.Sum_Of_Squares_Smallest_Index = Sum_Of_Squares_Smallest_Index;

            if (Sum_Of_Squares_Smallest_Index - 2 < 0 ||
                Sum_Of_Squares_Smallest_Index + 2 > Sum_Of_Squares_Mean.Length - 1)
            {
                rv.ErrorMessage = string.Format("Cannot locate the smallest normalized sum of squares (Index = {0})", Sum_Of_Squares_Smallest_Index);
                return(rv);
            }

            /* Solve the quadratic equation */
            for (i = 0; i <= 3; i++)
            {
                Quad[i] = Sum_Of_Squares_Mean[Sum_Of_Squares_Smallest_Index + i - 2];
            }

            A = -Quad[2] + (Quad[3] + Quad[1]) / 2.0;
            B = -3.0 * A + Quad[2] - Quad[1];
            C = Quad[1] - A - B;

            /* Calculate the time of minimum and uncertainty */
            T0             = -B / (2.0 * A);
            T0_Uncertainty = Math.Sqrt((4.0 * A * C - B * B) / (4.0 * A * A) / ((float)Normal_Points / 4.0 - 1.0));

            rv.T0                          = T0;
            rv.T0_Uncertainty              = T0_Uncertainty;
            rv.Time_Of_Minimum             = Time_Normal[1] + ((Sum_Of_Squares_Smallest_Index - 1) + (T0 - 2.0)) * Time_Interval;
            rv.Time_Of_Minimum_JD          = Time_First_JD + rv.Time_Of_Minimum;
            rv.Time_Of_Minimum_Uncertainty = T0_Uncertainty * Time_Interval;
            rv.Success                     = true;

            rv.Summary_File.Add(string.Format("      Time_First               Number_Obs"));
            rv.Summary_File.Add(Time_First_JD.ToString("#########0.000000").PadLeft(20) + " " + Number_Obs.ToString("#########0").PadLeft(20));
            rv.Summary_File.Add(string.Format("\n               Time of minimum: \n"));
            rv.Summary_File.Add(string.Format("      Bins-Quadratic          Uncertainty"));
            rv.Summary_File.Add(T0.ToString("#########0.000000").PadLeft(20) + " " + T0_Uncertainty.ToString("#########0.000000").PadLeft(20));
            rv.Summary_File.Add(string.Format("      From Time_First         Uncertainty"));
            rv.Summary_File.Add(rv.Time_Of_Minimum.ToString("#########0.000000").PadLeft(20) + " " + rv.Time_Of_Minimum_Uncertainty.ToString("#########0.000000").PadLeft(20));
            rv.Summary_File.Add(string.Format("      Absolute                Uncertainty"));
            rv.Summary_File.Add(rv.Time_Of_Minimum_JD.ToString("#########0.000000").PadLeft(20) + " " + rv.Time_Of_Minimum_Uncertainty.ToString("#########0.000000").PadLeft(20));

            /* Finish */
            return(rv);
        }
Ejemplo n.º 7
0
 static bool Do0(T0 t) {
   Nullable<T0> n = new Nullable<T0>(t);
   return Ensure(n.HasValue && n.Value == t);
 }
Ejemplo n.º 8
0
 protected ParentType(T0 value) : base(value)
 {
 }
 public void Fire(T0 t0, T1 t1) => _callback?.Invoke(t0, t1);
Ejemplo n.º 10
0
 public V3(T0 value) => m_value = value;
Ejemplo n.º 11
0
 static T1 F(T0 t0) => new T1(t0.Value + 1);
Ejemplo n.º 12
0
 public static void m1(this T0 _p0)
 {
 }
Ejemplo n.º 13
0
 /// <summary>Method mixing generic type parameters of parent class, nested class, and method.</summary>
 public void Baz <T4, T5>(T0 a, List <T1> b, T2 c, List <T3> d, T4 e, List <T5> f)
 {
 }
Ejemplo n.º 14
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;
        }