Example #1
0
        /// <summary>
        /// Renders a tick by drawing an lot of segments
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        private void RenderTickArc(Axis axis, AngleAxis angleAxis, double x, OxyPen pen)
        {
            // caution: make sure angleAxis.UpdateActualMaxMin(); has been called
            var minAngle = angleAxis.ActualMinimum;
            var maxAngle = angleAxis.ActualMaximum;

            // number of segment to draw a full circle
            // - decrease if you want get more speed
            // - increase if you want more detail
            // (making a public property of it would be a great idea)
            const double MaxSegments = 90.0;

            // compute the actual number of segments
            var segmentCount = (int)(MaxSegments * Math.Abs(angleAxis.EndAngle - angleAxis.StartAngle) / 360.0);

            var angleStep = (maxAngle - minAngle) / (segmentCount - 1);

            var points = new List <ScreenPoint>();

            for (var i = 0; i < segmentCount; i++)
            {
                var angle = minAngle + (i * angleStep);
                points.Add(axis.Transform(x, angle, angleAxis));
            }

            this.RenderContext.DrawLine(points, pen.Color, pen.Thickness, pen.ActualDashArray);
        }
Example #2
0
 /// <summary>
 /// Creates the pens.
 /// </summary>
 /// <param name="axis">The axis.</param>
 protected virtual void CreatePens(Axis axis)
 {
     this.MinorPen     = OxyPen.Create(axis.MinorGridlineColor, axis.MinorGridlineThickness, axis.MinorGridlineStyle);
     this.MajorPen     = OxyPen.Create(axis.MajorGridlineColor, axis.MajorGridlineThickness, axis.MajorGridlineStyle);
     this.MinorTickPen = OxyPen.Create(axis.TicklineColor, axis.MinorGridlineThickness);
     this.MajorTickPen = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
     this.ZeroPen      = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
     this.ExtraPen     = OxyPen.Create(axis.ExtraGridlineColor, axis.ExtraGridlineThickness, axis.ExtraGridlineStyle);
     this.AxislinePen  = OxyPen.Create(axis.AxislineColor, axis.AxislineThickness, axis.AxislineStyle);
 }
Example #3
0
        /// <summary>
        /// Creates the pens.
        /// </summary>
        /// <param name="axis">The axis.</param>
        protected virtual void CreatePens(Axis axis)
        {
            var minorTickColor = axis.MinorTicklineColor.IsAutomatic() ? axis.TicklineColor : axis.MinorTicklineColor;

            this.MinorPen     = OxyPen.Create(axis.MinorGridlineColor, axis.MinorGridlineThickness, axis.MinorGridlineStyle);
            this.MajorPen     = OxyPen.Create(axis.MajorGridlineColor, axis.MajorGridlineThickness, axis.MajorGridlineStyle);
            this.MinorTickPen = OxyPen.Create(minorTickColor, axis.MinorGridlineThickness);
            this.MajorTickPen = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
            this.ZeroPen      = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
            this.ExtraPen     = OxyPen.Create(axis.ExtraGridlineColor, axis.ExtraGridlineThickness, axis.ExtraGridlineStyle);
            this.AxislinePen  = OxyPen.Create(axis.AxislineColor, axis.AxislineThickness, axis.AxislineStyle);
        }
Example #4
0
        /// <summary>
        /// Renders a tick by drawing an ellipse
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        private void RenderTickCircle(Axis axis, Axis angleAxis, double x, OxyPen pen)
        {
            var zero   = angleAxis.Offset;
            var center = axis.Transform(axis.ActualMinimum, zero, angleAxis);
            var right  = axis.Transform(x, zero, angleAxis).X;
            var radius = right - center.X;
            var width  = radius * 2;
            var left   = right - width;
            var top    = center.Y - radius;
            var height = width;

            this.RenderContext.DrawEllipse(new OxyRect(left, top, width, height), OxyColors.Undefined, pen.Color, pen.Thickness);
        }
Example #5
0
        /// <summary>
        /// Renders a tick, chooses the best implementation
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        private void RenderTick(Axis axis, AngleAxis angleAxis, double x, OxyPen pen)
        {
            var isFullCircle = Math.Abs(Math.Abs(angleAxis.EndAngle - angleAxis.StartAngle) - 360) < 1e-6;

            if (isFullCircle && pen.ActualDashArray == null)
            {
                this.RenderTickCircle(axis, angleAxis, x, pen);
            }
            else
            {
                this.RenderTickArc(axis, angleAxis, x, pen);
            }
        }
        /// <summary>
        /// Draws text with metrics.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="font">The font.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="expectedWidth">The expected width.</param>
        /// <param name="expectedHeight">The expected height.</param>
        /// <param name="baseline">The baseline position.</param>
        /// <param name="xheight">The x-height position.</param>
        /// <param name="ascent">The ascent position.</param>
        /// <param name="descent">The descent position.</param>
        /// <param name="before">The before position.</param>
        /// <param name="after">The after position.</param>
        /// <param name="platform">The platform.</param>
        /// <returns>
        /// A plot model.
        /// </returns>
        private static PlotModel DrawTextWithMetrics(string text, string font, double fontSize, double expectedWidth, double expectedHeight, double baseline, double xheight, double ascent, double descent, double before, double after, string platform)
        {
            // http://msdn.microsoft.com/en-us/library/ms742190(v=vs.110).aspx
            // http://msdn.microsoft.com/en-us/library/xwf9s90b(v=vs.110).aspx
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms533824(v=vs.85).aspx
            // https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
            var model = new PlotModel();

            model.Annotations.Add(
                new DelegateAnnotation(
                    rc =>
            {
                var size         = rc.MeasureText(text, font, fontSize);
                var expectedSize = new OxySize(expectedWidth, expectedHeight);
                rc.DrawText(new ScreenPoint(300, 50), "Font size: " + fontSize, OxyColors.Black, font, 12);
                rc.DrawText(new ScreenPoint(300, 70), "Actual size: " + size.ToString("0.00", CultureInfo.InvariantCulture), OxyColors.Black, font, 12);
                rc.DrawText(new ScreenPoint(300, 90), "Size on " + platform + ": " + expectedSize.ToString("0.00", CultureInfo.InvariantCulture), OxyColors.Green, font, 12);

                var p = new ScreenPoint(20, 50);
                rc.DrawText(p, text, OxyColors.Black, font, fontSize);

                rc.FillCircle(p, 3, OxyColors.Black);

                // actual bounds
                rc.DrawRectangle(new OxyRect(p, size), OxyColors.Undefined, OxyColors.Black);

                // Expected bounds (WPF)
                rc.DrawRectangle(new OxyRect(p, expectedSize), OxyColors.Undefined, OxyColors.Green);

                var color = OxyColor.FromAColor(180, OxyColors.Red);
                var pen   = new OxyPen(color);

                // Expected vertical positions (WPF)
                var x1 = p.X - 10;
                var x2 = p.X + expectedSize.Width + 10;
                rc.DrawLine(x1, baseline, x2, baseline, pen);
                rc.DrawLine(x1, xheight, x2, xheight, pen);
                rc.DrawLine(x1, ascent, x2, ascent, pen);
                rc.DrawLine(x1, descent, x2, descent, pen);

                // Expected horizonal positions (WPF)
                var y1 = p.Y - 10;
                var y2 = p.Y + expectedSize.Height + 10;
                rc.DrawLine(before, y1, before, y2, pen);
                rc.DrawLine(after, y1, after, y2, pen);
            }));

            model.MouseDown += (s, e) => Debug.WriteLine(e.Position);

            return(model);
        }
        /// <summary>
        /// Renders a tick by drawing an lot of segments
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        /// <param name="startAngle">The start angle.</param>
        /// <param name="endAngle">The end angle.</param>
        private void RenderTickArc(Axis axis, AngleAxis angleAxis, double x, OxyPen pen, double startAngle, double endAngle)
        {
            if (startAngle > endAngle)
            {
            }
            // caution: make sure angleAxis.UpdateActualMaxMin(); has been called

            // number of segment to draw a full circle
            // - decrease if you want get more speed
            // - increase if you want more detail
            // (making a public property of it would be a great idea)

            // compute the actual number of segments
            var segmentCount = (int)(MaxSegments * Math.Abs(endAngle - startAngle) / 360.0);

            if (angleAxis.FractionUnit == Math.PI || angleAxis.ActualMaximum == 2 * Math.PI)
            {
                segmentCount = (int)(MaxSegments * Math.Abs(endAngle - startAngle) / (2 * Math.PI));
                startAngle  *= rad;
                endAngle    *= rad;
            }

            segmentCount = Math.Max(segmentCount, 2);
            segmentCount = Math.Min(segmentCount, (int)MaxSegments);
            var angleStep = Math.Abs(endAngle - startAngle) / (segmentCount - 1);

            var points = new List <ScreenPoint>();

            for (var i = 0; i < segmentCount; i++)
            {
                var         angle = startAngle + (i * angleStep);
                ScreenPoint toadd = axis.Transform(x, angle, angleAxis);
                points.Add(toadd);
            }

            this.RenderContext.DrawLine(points, pen.Color, pen.Thickness, axis.EdgeRenderingMode, pen.ActualDashArray);
        }
        /// <summary>
        /// Renders the specified axis.
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="pass">The pass.</param>
        /// <exception cref="System.NullReferenceException">Angle axis should not be <c>null</c>.</exception>
        public override void Render(Axis axis, int pass)
        {
            base.Render(axis, pass);

            var angleAxis     = this.Plot.DefaultAngleAxis;
            var magnitudeAxis = this.Plot.DefaultMagnitudeAxis;

            if (angleAxis == null)
            {
                throw new NullReferenceException("Angle axis should not be null.");
            }

            angleAxis.UpdateActualMaxMin();

            double  topdistance    = Math.Abs(axis.PlotModel.PlotArea.Top - magnitudeAxis.MidPoint.Y);
            double  bottomdistance = Math.Abs(axis.PlotModel.PlotArea.Bottom - magnitudeAxis.MidPoint.Y);
            double  leftdistance   = Math.Abs(axis.PlotModel.PlotArea.Left - magnitudeAxis.MidPoint.X);
            double  rightdistance  = Math.Abs(axis.PlotModel.PlotArea.Right - magnitudeAxis.MidPoint.X);
            OxyRect distancerect   = axis.PlotModel.PlotArea.Offset(-magnitudeAxis.MidPoint.X, -magnitudeAxis.MidPoint.Y);

            double cornerangle_topright = -degree *Math.Atan2(distancerect.Top, distancerect.Right);

            double cornerangle_topleft = -degree *Math.Atan2(distancerect.Top, distancerect.Left);

            double cornerangle_bottomleft  = 360 - degree * Math.Atan2(distancerect.Bottom, distancerect.Left);
            double cornerangle_bottomright = 360 - degree * Math.Atan2(distancerect.Bottom, distancerect.Right);

            // detect and filter dodgy values caused by zero values
            if (cornerangle_topleft < 0)
            {
                cornerangle_topleft += 360;
            }
            if (cornerangle_bottomleft > 360)
            {
                cornerangle_bottomleft -= 360;
            }

            double cornerdistance_topright    = Math.Sqrt(Math.Pow(distancerect.Top, 2) + Math.Pow(distancerect.Right, 2));
            double cornerdistance_topleft     = Math.Sqrt(Math.Pow(distancerect.Top, 2) + Math.Pow(distancerect.Left, 2));
            double cornerdistance_bottomleft  = Math.Sqrt(Math.Pow(distancerect.Bottom, 2) + Math.Pow(distancerect.Left, 2));
            double cornerdistance_bottomright = Math.Sqrt(Math.Pow(distancerect.Bottom, 2) + Math.Pow(distancerect.Right, 2));

            if (pass == 0 && this.MinorPen != null)
            {
                OxyPen pen = this.MinorPen;

                foreach (var tickValue in this.MinorTickValues)
                {
                    //a circle consists - in this case - of 4 arcs
                    //the start and end of each arc has to be computed

                    double r = axis.Transform(tickValue);

                    //this works by putting the limits of the plotarea into the circular equation and solving it to gain t for each intersection

                    double startangle_0_90    = 0;
                    double endangle_0_90      = 90;
                    double startangle_90_180  = 90;
                    double endangle_90_180    = 180;
                    double startangle_180_270 = 180;
                    double endangle_180_270   = 270;
                    double startangle_270_360 = 270;
                    double endangle_270_360   = 360;

                    double rightportion  = rightdistance / r;
                    double topportion    = topdistance / r;
                    double leftportion   = leftdistance / r;
                    double bottomportion = bottomdistance / r;

                    if (r > rightdistance)
                    {
                        //will hit the right bound
                        endangle_270_360 = 360 - degree * Math.Acos(rightportion);
                        startangle_0_90  = degree * Math.Acos(rightportion);
                    }
                    if (r > topdistance)
                    {
                        //will hit the top bound
                        endangle_0_90     = degree * Math.Asin(topportion);
                        startangle_90_180 = 180 - degree * Math.Asin(topportion);
                    }
                    if (r > leftdistance)
                    {
                        //will hit the left bound
                        endangle_90_180    = 180 - degree * Math.Acos(leftportion);
                        startangle_180_270 = 180 + degree * Math.Acos(leftportion);
                    }
                    if (r > bottomdistance)
                    {
                        //will hit the bottom bound
                        endangle_180_270   = 180 + degree * Math.Asin(bottomportion);
                        startangle_270_360 = 360 - degree * Math.Asin(bottomportion);
                    }

                    //Top right
                    if (r <= cornerdistance_topright)
                    {
                        if (startangle_0_90 < cornerangle_topright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (startangle_0_90 + angleAxis.Offset), (cornerangle_topright + angleAxis.Offset));
                        }
                        if (cornerangle_topright < endangle_0_90)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (cornerangle_topright + angleAxis.Offset), (endangle_0_90 + angleAxis.Offset));
                        }
                    }

                    //Top left
                    if (r <= cornerdistance_topleft)
                    {
                        if (startangle_90_180 < cornerangle_topleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_90_180 + angleAxis.Offset, cornerangle_topleft + angleAxis.Offset);
                        }
                        if (cornerangle_topleft < endangle_90_180)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_topleft + angleAxis.Offset, endangle_90_180 + angleAxis.Offset);
                        }
                    }

                    //Bottom left
                    if (r <= cornerdistance_bottomleft)
                    {
                        if (startangle_180_270 < cornerangle_bottomleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_180_270 + angleAxis.Offset, cornerangle_bottomleft + angleAxis.Offset);
                        }
                        if (cornerangle_bottomleft < endangle_180_270)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomleft + angleAxis.Offset, endangle_180_270 + angleAxis.Offset);
                        }
                    }

                    //Bottom right
                    if (r <= cornerdistance_bottomright)
                    {
                        if (startangle_270_360 < cornerangle_bottomright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_270_360 + angleAxis.Offset, cornerangle_bottomright + angleAxis.Offset);
                        }
                        if (cornerangle_bottomright < endangle_270_360)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomright + angleAxis.Offset, endangle_270_360 + angleAxis.Offset);
                        }
                    }
                }
            }

            if (pass == 0 && this.MajorPen != null)
            {
                OxyPen pen = this.MajorPen;
                foreach (var tickValue in this.MajorTickValues)
                {
                    //a circle consists - in this case - of 4 arcs
                    //the start and end of each arc has to be computed

                    double r = axis.Transform(tickValue);

                    //this works by putting the limits of the plotarea into the circular equation and solving it to gain t for each intersection

                    double startangle_0_90    = 0;
                    double endangle_0_90      = 90;
                    double startangle_90_180  = 90;
                    double endangle_90_180    = 180;
                    double startangle_180_270 = 180;
                    double endangle_180_270   = 270;
                    double startangle_270_360 = 270;
                    double endangle_270_360   = 360;

                    double rightportion  = rightdistance / r;
                    double topportion    = topdistance / r;
                    double leftportion   = leftdistance / r;
                    double bottomportion = bottomdistance / r;

                    if (r > rightdistance)
                    {
                        //will hit the right bound
                        endangle_270_360 = 360 - degree * Math.Acos(rightportion);
                        startangle_0_90  = degree * Math.Acos(rightportion);
                    }
                    if (r > topdistance)
                    {
                        //will hit the top bound
                        endangle_0_90     = degree * Math.Asin(topportion);
                        startangle_90_180 = 180 - degree * Math.Asin(topportion);
                    }
                    if (r > leftdistance)
                    {
                        //will hit the left bound
                        endangle_90_180    = 180 - degree * Math.Acos(leftportion);
                        startangle_180_270 = 180 + degree * Math.Acos(leftportion);
                    }
                    if (r > bottomdistance)
                    {
                        //will hit the bottom bound
                        endangle_180_270   = 180 + degree * Math.Asin(bottomportion);
                        startangle_270_360 = 360 - degree * Math.Asin(bottomportion);
                    }

                    //Top right
                    if (r <= cornerdistance_topright)
                    {
                        if (startangle_0_90 < cornerangle_topright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (startangle_0_90 + angleAxis.Offset), (cornerangle_topright + angleAxis.Offset));
                        }
                        if (cornerangle_topright < endangle_0_90)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (cornerangle_topright + angleAxis.Offset), (endangle_0_90 + angleAxis.Offset));
                        }
                    }

                    //Top left
                    if (r <= cornerdistance_topleft)
                    {
                        if (startangle_90_180 < cornerangle_topleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_90_180 + angleAxis.Offset, cornerangle_topleft + angleAxis.Offset);
                        }
                        if (cornerangle_topleft < endangle_90_180)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_topleft + angleAxis.Offset, endangle_90_180 + angleAxis.Offset);
                        }
                    }

                    //Bottom left
                    if (r <= cornerdistance_bottomleft)
                    {
                        if (startangle_180_270 < cornerangle_bottomleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_180_270 + angleAxis.Offset, cornerangle_bottomleft + angleAxis.Offset);
                        }
                        if (cornerangle_bottomleft < endangle_180_270)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomleft + angleAxis.Offset, endangle_180_270 + angleAxis.Offset);
                        }
                    }

                    //Bottom right
                    if (r <= cornerdistance_bottomright)
                    {
                        if (startangle_270_360 < cornerangle_bottomright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_270_360 + angleAxis.Offset, cornerangle_bottomright + angleAxis.Offset);
                        }
                        if (cornerangle_bottomright < endangle_270_360)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomright + angleAxis.Offset, endangle_270_360 + angleAxis.Offset);
                        }
                    }
                }
            }

            if (pass == 1)
            {
                foreach (var tickValue in this.MajorLabelValues)
                {
                    this.RenderTickText(axis, tickValue, angleAxis);
                }
            }
        }
        /// <summary>
        /// Renders a tick by drawing an lot of segments
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        private void RenderTickArc(Axis axis, AngleAxis angleAxis, double x, OxyPen pen)
        {
            // caution: make sure angleAxis.UpdateActualMaxMin(); has been called
            var minAngle = angleAxis.ActualMinimum;
            var maxAngle = angleAxis.ActualMaximum;

            // number of segment to draw a full circle
            // - decrease if you want get more speed
            // - increase if you want more detail
            // (making a public property of it would be a great idea)
            const double MaxSegments = 90.0;

            // compute the actual number of segments
            var segmentCount = (int)(MaxSegments * Math.Abs(angleAxis.EndAngle - angleAxis.StartAngle) / 360.0);

            var angleStep = (maxAngle - minAngle) / (segmentCount - 1);

            var points = new List<ScreenPoint>();

            for (var i = 0; i < segmentCount; i++)
            {
                var angle = minAngle + (i * angleStep);
                points.Add(axis.Transform(x, angle, angleAxis));
            }

            this.RenderContext.DrawLine(points, pen.Color, pen.Thickness, pen.ActualDashArray);
        }
        /// <summary>
        /// Renders a tick by drawing an ellipse
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        private void RenderTickCircle(Axis axis, Axis angleAxis, double x, OxyPen pen)
        {
            var zero = angleAxis.Offset;
            var center = axis.Transform(axis.ActualMinimum, zero, angleAxis);
            var right = axis.Transform(x, zero, angleAxis).X;
            var radius = right - center.X;
            var width = radius * 2;
            var left = right - width;
            var top = center.Y - radius;
            var height = width;

            this.RenderContext.DrawEllipse(new OxyRect(left, top, width, height), OxyColors.Undefined, pen.Color, pen.Thickness);
        }
        /// <summary>
        /// Renders a tick, chooses the best implementation
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="angleAxis">The angle axis.</param>
        /// <param name="x">The x-value.</param>
        /// <param name="pen">The pen.</param>
        private void RenderTick(Axis axis, AngleAxis angleAxis, double x, OxyPen pen)
        {
            var isFullCircle = Math.Abs(Math.Abs(angleAxis.EndAngle - angleAxis.StartAngle) - 360) < 1e-6;

            if (isFullCircle && pen.ActualDashArray == null)
            {
                this.RenderTickCircle(axis, angleAxis, x, pen);
            }
            else
            {
                this.RenderTickArc(axis, angleAxis, x, pen);
            }
        }
Example #12
0
        public static PlotModel Clipping()
        {
            var model = new PlotModel();

            model.Annotations.Add(new DelegateAnnotation(rc =>
            {
                void DrawClipRect(OxyRect clipRect)
                {
                    var pen = new OxyPen(OxyColors.Black, 2, LineStyle.Dash);
                    rc.DrawLine(clipRect.Left, clipRect.Top, clipRect.Right, clipRect.Top, pen, EdgeRenderingMode.Automatic);
                    rc.DrawLine(clipRect.Right, clipRect.Top, clipRect.Right, clipRect.Bottom, pen, EdgeRenderingMode.Automatic);
                    rc.DrawLine(clipRect.Right, clipRect.Bottom, clipRect.Left, clipRect.Bottom, pen, EdgeRenderingMode.Automatic);
                    rc.DrawLine(clipRect.Left, clipRect.Bottom, clipRect.Left, clipRect.Top, pen, EdgeRenderingMode.Automatic);
                }

                var currentLine                = 20d;
                const double lineHeight        = 60;
                const double clipRectSize      = 40;
                const double clipRectMargin    = 20;
                const double testCaseMargin    = 20;
                const double descriptionMargin = 200;
                var rect = new OxyRect();

                void DrawCircle(ScreenPoint center)
                {
                    rc.DrawCircle(center, clipRectSize * 0.58, OxyColors.CornflowerBlue, OxyColors.Undefined, 0, EdgeRenderingMode.Automatic);
                }

                void DrawDescription(string text)
                {
                    var p = new ScreenPoint(clipRectMargin + clipRectSize + testCaseMargin + descriptionMargin, currentLine);
                    rc.DrawText(p, text, OxyColors.Black, fontSize: 12, verticalAlignment: VerticalAlignment.Middle);
                }

                void DrawTestCase(string text)
                {
                    var p = new ScreenPoint(clipRectMargin + clipRectSize + testCaseMargin, currentLine);
                    rc.DrawText(p, text, OxyColors.Black, fontSize: 12, verticalAlignment: VerticalAlignment.Middle);
                }

                void DrawHeader(string text, double offset)
                {
                    rc.DrawText(new ScreenPoint(offset, 15), text, OxyColors.Black, fontSize: 12, fontWeight: 700);
                }

                void NextLine()
                {
                    currentLine += lineHeight;
                    rect         = new OxyRect(clipRectMargin, currentLine - clipRectSize / 2, clipRectSize, clipRectSize);
                }

                DrawHeader("Actual", clipRectMargin);
                DrawHeader("Test Case", clipRectMargin + clipRectSize + testCaseMargin);
                DrawHeader("Expected", clipRectMargin + clipRectSize + testCaseMargin + descriptionMargin);

                //-------------
                NextLine();
                rc.PushClip(rect);
                rc.PopClip();
                DrawCircle(rect.Center);

                DrawTestCase("1. Push clipping rectangle\n2. Pop clipping rectangle\n3. Draw circle");
                DrawDescription("The circle should be fully drawn.");

                //-------------
                NextLine();
                rc.PushClip(rect);
                DrawCircle(rect.Center);

                rc.PopClip();

                DrawClipRect(rect);
                DrawTestCase("1. Push clipping rectangle\n2. Draw Circle");
                DrawDescription("The circle should be clipped.");

                //-------------
                NextLine();
                var rect2 = rect.Deflate(new OxyThickness(rect.Height * 0.25));
                rc.PushClip(rect);
                rc.PushClip(rect2);

                DrawCircle(rect.Center);

                rc.PopClip();
                rc.PopClip();

                DrawClipRect(rect);
                DrawClipRect(rect2);
                DrawTestCase("1. Push large clipping rectangle\n2. Push small clipping rectangle\n3. Draw Circle");
                DrawDescription("The circle should be clipped to the small clipping rectangle.");

                //-------------
                NextLine();
                rect2 = rect.Deflate(new OxyThickness(rect.Height * 0.25));
                rc.PushClip(rect2);
                rc.PushClip(rect);

                DrawCircle(rect.Center);

                rc.PopClip();
                rc.PopClip();

                DrawClipRect(rect);
                DrawClipRect(rect2);
                DrawTestCase("1. Push small clipping rectangle\n2. Push large clipping rectangle\n3. Draw Circle");
                DrawDescription("The circle should be clipped to the small clipping rectangle.");

                //-------------
                NextLine();
                rect2 = rect.Offset(rect.Width / 2, rect.Height / 2).Deflate(new OxyThickness(rect.Height * 0.25));
                rc.PushClip(rect);
                rc.PushClip(rect2);

                DrawCircle(rect.Center);

                rc.PopClip();
                rc.PopClip();

                DrawClipRect(rect);
                DrawClipRect(rect2);
                DrawTestCase("1. Push large clipping rectangle\n2. Push small clipping rectangle\n3. Draw Circle");
                DrawDescription("The circle should be clipped to the intersection of the clipping rectangles.");

                //-------------
                NextLine();
                rect2 = rect.Offset(rect.Width / 2, rect.Height / 2).Deflate(new OxyThickness(rect.Height * 0.25));
                rc.PushClip(rect);
                rc.PushClip(rect2);

                rc.PopClip();

                DrawCircle(rect.Center);

                rc.PopClip();

                DrawClipRect(rect);
                DrawClipRect(rect2);
                DrawTestCase("1. Push large clipping rectangle\n2. Push small clipping rectangle\n3. Pop small clipping rectangle\n4. Draw Circle");
                DrawDescription("The circle should be clipped to the large clipping rectangle.");

                //-------------
                NextLine();
                var rect3 = rect.Offset(rect.Width / 3, rect.Height / 3).Deflate(new OxyThickness(rect.Height * 0.25));
                var rect4 = rect.Offset(-rect.Width / 3, -rect.Height / 3).Deflate(new OxyThickness(rect.Height * 0.25));
                rc.PushClip(rect3);
                rc.PushClip(rect4);

                DrawCircle(rect.Center);

                rc.PopClip();
                rc.PopClip();

                DrawClipRect(rect3);
                DrawClipRect(rect4);
                DrawTestCase("1. Push clipping rectangle\n2. Push second clipping rectangle\n3. Draw Circle");
                DrawDescription("The circle should not be drawn at all.");

                //-------------
                NextLine();
                using (rc.AutoResetClip(rect))
                {
                    rc.DrawText(rect.Center, "OxyPlot", OxyColors.CornflowerBlue, fontSize: 15, horizontalAlignment: HorizontalAlignment.Center, verticalAlignment: VerticalAlignment.Middle);
                }

                DrawClipRect(rect);
                DrawTestCase("1. Push clipping rectangle\n2. Draw Text");
                DrawDescription("The text should be clipped.");
            }));

            return(model);
        }
Example #13
0
        /// <summary>
        /// Creates the pens.
        /// </summary>
        /// <param name="axis">The axis.</param>
        protected virtual void CreatePens(Axis axis)
        {
            var minorTickColor = axis.MinorTicklineColor.IsAutomatic() ? axis.TicklineColor : axis.MinorTicklineColor;

            this.MinorPen = OxyPen.Create(axis.MinorGridlineColor, axis.MinorGridlineThickness, axis.MinorGridlineStyle);
            this.MajorPen = OxyPen.Create(axis.MajorGridlineColor, axis.MajorGridlineThickness, axis.MajorGridlineStyle);
            this.MinorTickPen = OxyPen.Create(minorTickColor, axis.MinorGridlineThickness);
            this.MajorTickPen = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
            this.ZeroPen = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
            this.ExtraPen = OxyPen.Create(axis.ExtraGridlineColor, axis.ExtraGridlineThickness, axis.ExtraGridlineStyle);
            this.AxislinePen = OxyPen.Create(axis.AxislineColor, axis.AxislineThickness, axis.AxislineStyle);
        }
Example #14
0
 /// <summary>
 /// Creates the pens.
 /// </summary>
 /// <param name="axis">The axis.</param>
 protected virtual void CreatePens(Axis axis)
 {
     this.MinorPen = OxyPen.Create(axis.MinorGridlineColor, axis.MinorGridlineThickness, axis.MinorGridlineStyle);
     this.MajorPen = OxyPen.Create(axis.MajorGridlineColor, axis.MajorGridlineThickness, axis.MajorGridlineStyle);
     this.MinorTickPen = OxyPen.Create(axis.TicklineColor, axis.MinorGridlineThickness);
     this.MajorTickPen = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
     this.ZeroPen = OxyPen.Create(axis.TicklineColor, axis.MajorGridlineThickness);
     this.ExtraPen = OxyPen.Create(axis.ExtraGridlineColor, axis.ExtraGridlineThickness, axis.ExtraGridlineStyle);
     this.AxislinePen = OxyPen.Create(axis.AxislineColor, axis.AxislineThickness, axis.AxislineStyle);
 }
        /// <summary>
        /// Renders the specified axis.
        /// </summary>
        /// <param name="axis">The axis.</param>
        /// <param name="pass">The pass.</param>
        /// <exception cref="System.NullReferenceException">Angle axis should not be <c>null</c>.</exception>
        public override void Render(Axis axis, int pass)
        {
            base.Render(axis, pass);

            var angleAxis     = this.Plot.DefaultAngleAxis;
            var magnitudeAxis = this.Plot.DefaultMagnitudeAxis;

            if (angleAxis == null)
            {
                throw new NullReferenceException("Angle axis should not be null.");
            }

            angleAxis.UpdateActualMaxMin();

            double  topdistance    = Math.Abs(axis.PlotModel.PlotArea.Top - magnitudeAxis.MidPoint.Y);
            double  bottomdistance = Math.Abs(axis.PlotModel.PlotArea.Bottom - magnitudeAxis.MidPoint.Y);
            double  leftdistance   = Math.Abs(axis.PlotModel.PlotArea.Left - magnitudeAxis.MidPoint.X);
            double  rightdistance  = Math.Abs(axis.PlotModel.PlotArea.Right - magnitudeAxis.MidPoint.X);
            OxyRect plotrect       = axis.PlotModel.PlotArea;
            OxyRect distancerect   = axis.PlotModel.PlotArea.Offset(-magnitudeAxis.MidPoint.X, -magnitudeAxis.MidPoint.Y);
            OxyRect maxtickrect    = new OxyRect(new ScreenPoint(axis.InverseTransform(distancerect.Left), axis.InverseTransform(distancerect.Top)), new ScreenPoint(axis.InverseTransform(distancerect.Right), axis.InverseTransform(distancerect.Bottom)));

            double cornerangle_topright = -degree *Math.Atan2(maxtickrect.Top, maxtickrect.Right);

            double cornerangle_topleft = -degree *Math.Atan2(maxtickrect.Top, maxtickrect.Left);

            double cornerangle_bottomleft  = 360 - degree * Math.Atan2(maxtickrect.Bottom, maxtickrect.Left);
            double cornerangle_bottomright = 360 - degree * Math.Atan2(maxtickrect.Bottom, maxtickrect.Right);

            // detect and filter dodgy values (these checks appear to be sufficient)
            if (cornerangle_topleft < 0)
            {
                cornerangle_topleft += 360;
            }
            if (cornerangle_bottomleft > 360)
            {
                cornerangle_bottomleft -= 360;
            }

            double cornerdistance_topright    = Math.Sqrt(Math.Pow(distancerect.Top, 2) + Math.Pow(distancerect.Right, 2));
            double cornerdistance_topleft     = Math.Sqrt(Math.Pow(distancerect.Top, 2) + Math.Pow(distancerect.Left, 2));
            double cornerdistance_bottomleft  = Math.Sqrt(Math.Pow(distancerect.Bottom, 2) + Math.Pow(distancerect.Left, 2));
            double cornerdistance_bottomright = Math.Sqrt(Math.Pow(distancerect.Bottom, 2) + Math.Pow(distancerect.Right, 2));

            double maxtick_topright    = axis.InverseTransform(cornerdistance_topright);
            double maxtick_topleft     = axis.InverseTransform(cornerdistance_topleft);
            double maxtick_bottomleft  = axis.InverseTransform(cornerdistance_bottomleft);
            double maxtick_bottomright = axis.InverseTransform(cornerdistance_bottomright);

            double maxdistance = Math.Max(cornerdistance_topright, Math.Max(cornerdistance_topleft, Math.Max(cornerdistance_bottomleft, cornerdistance_bottomright)));
            double maxtick = new double[] { maxtick_topright, maxtick_topleft, maxtick_bottomleft, maxtick_bottomright }.Max();
            double mintick = new double[] { maxtick_topright, maxtick_topleft, maxtick_bottomleft, maxtick_bottomright }.Min();

            List <double> majorticks = new List <double>();

            majorticks.AddRange(this.MajorTickValues);
            ExtendTickList(ref majorticks, maxtick);

            List <double> minorticks = new List <double>();

            minorticks.AddRange(this.MinorTickValues);
            ExtendTickList(ref minorticks, maxtick);

            List <double> textticks = new List <double>();
            //now the axis angle is relevant
            double axisorientation = (360 + angleAxis.StartAngle) % 360;
            double textticklength  = GetTickLength(axisorientation, maxtickrect);

            textticks.AddRange(this.MajorTickValues);
            ExtendTickList(ref textticks, textticklength);

            var majorTicks = majorticks.Where(x => x > axis.ActualMinimum && x <= maxtick).ToArray();

            if (pass == 0 && this.MinorPen != null)
            {
                OxyPen pen = this.MinorPen;
                //var minorTicks = this.MinorTickValues.Where(x => x >= axis.ActualMinimum && x <= axis.ActualMaximum && !majorTicks.Contains(x)).ToArray();
                var minorTicks = minorticks.Where(x => x >= axis.ActualMinimum && x <= maxtick && !majorTicks.Contains(x)).ToArray();

                foreach (var tickValue in minorTicks)
                {
                    //a circle consists - in this case - of 4 arcs
                    //the start and end of each arc has to be computed

                    double r = axis.Transform(tickValue);

                    //this works by putting the limits of the plotarea into the circular equation and solving it to gain t for each intersection

                    //y=r*sin(t)+ym
                    //t=asin((y-ym)/r)
                    //x=r*cos(t)+xm
                    //t=acos((x-xm)/r)

                    double startangle_0_90    = 0;
                    double endangle_0_90      = 90;
                    double startangle_90_180  = 90;
                    double endangle_90_180    = 180;
                    double startangle_180_270 = 180;
                    double endangle_180_270   = 270;
                    double startangle_270_360 = 270;
                    double endangle_270_360   = 360;

                    double rightportion  = rightdistance / r;
                    double topportion    = topdistance / r;
                    double leftportion   = leftdistance / r;
                    double bottomportion = bottomdistance / r;

                    if (r > rightdistance)
                    {
                        //will hit the right bound
                        endangle_270_360 = 360 - degree * Math.Acos(rightportion);
                        startangle_0_90  = degree * Math.Acos(rightportion);
                    }
                    if (r > topdistance)
                    {
                        //will hit the top bound
                        endangle_0_90     = degree * Math.Asin(topportion);
                        startangle_90_180 = 180 - degree * Math.Asin(topportion);
                    }
                    if (r > leftdistance)
                    {
                        //will hit the left bound
                        endangle_90_180    = 180 - degree * Math.Acos(leftportion);
                        startangle_180_270 = 180 + degree * Math.Acos(leftportion);
                    }
                    if (r > bottomdistance)
                    {
                        //will hit the bottom bound
                        endangle_180_270   = 180 + degree * Math.Asin(bottomportion);
                        startangle_270_360 = 360 - degree * Math.Asin(bottomportion);
                    }

                    //Top right
                    if (r <= cornerdistance_topright)
                    {
                        if (startangle_0_90 < cornerangle_topright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (startangle_0_90 + angleAxis.Offset), (cornerangle_topright + angleAxis.Offset));
                        }
                        if (cornerangle_topright < endangle_0_90)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (cornerangle_topright + angleAxis.Offset), (endangle_0_90 + angleAxis.Offset));
                        }
                    }

                    //Top left
                    if (r <= cornerdistance_topleft)
                    {
                        if (startangle_90_180 < cornerangle_topleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_90_180 + angleAxis.Offset, cornerangle_topleft + angleAxis.Offset);
                        }
                        if (cornerangle_topleft < endangle_90_180)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_topleft + angleAxis.Offset, endangle_90_180 + angleAxis.Offset);
                        }
                    }

                    //Bottom left
                    if (r <= cornerdistance_bottomleft)
                    {
                        if (startangle_180_270 < cornerangle_bottomleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_180_270 + angleAxis.Offset, cornerangle_bottomleft + angleAxis.Offset);
                        }
                        if (cornerangle_bottomleft < endangle_180_270)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomleft + angleAxis.Offset, endangle_180_270 + angleAxis.Offset);
                        }
                    }

                    //Bottom right
                    if (r <= cornerdistance_bottomright)
                    {
                        if (startangle_270_360 < cornerangle_bottomright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_270_360 + angleAxis.Offset, cornerangle_bottomright + angleAxis.Offset);
                        }
                        if (cornerangle_bottomright < endangle_270_360)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomright + angleAxis.Offset, endangle_270_360 + angleAxis.Offset);
                        }
                    }
                }
            }

            if (pass == 0 && this.MajorPen != null)
            {
                OxyPen pen = this.MajorPen;
                foreach (var tickValue in majorTicks)
                {
                    //a circle consists - in this case - of 4 arcs
                    //the start and end of each arc has to be computed

                    double r = axis.Transform(tickValue);

                    //this works by putting the limits of the plotarea into the circular equation and solving it to gain t for each intersection

                    //y=r*sin(t)+ym
                    //t=asin((y-ym)/r)
                    //x=r*cos(t)+xm
                    //t=acos((x-xm)/r)

                    double startangle_0_90    = 0;
                    double endangle_0_90      = 90;
                    double startangle_90_180  = 90;
                    double endangle_90_180    = 180;
                    double startangle_180_270 = 180;
                    double endangle_180_270   = 270;
                    double startangle_270_360 = 270;
                    double endangle_270_360   = 360;

                    double rightportion  = rightdistance / r;
                    double topportion    = topdistance / r;
                    double leftportion   = leftdistance / r;
                    double bottomportion = bottomdistance / r;

                    if (r > rightdistance)
                    {
                        //will hit the right bound
                        endangle_270_360 = 360 - degree * Math.Acos(rightportion);
                        startangle_0_90  = degree * Math.Acos(rightportion);
                    }
                    if (r > topdistance)
                    {
                        //will hit the top bound
                        endangle_0_90     = degree * Math.Asin(topportion);
                        startangle_90_180 = 180 - degree * Math.Asin(topportion);
                    }
                    if (r > leftdistance)
                    {
                        //will hit the left bound
                        endangle_90_180    = 180 - degree * Math.Acos(leftportion);
                        startangle_180_270 = 180 + degree * Math.Acos(leftportion);
                    }
                    if (r > bottomdistance)
                    {
                        //will hit the bottom bound
                        endangle_180_270   = 180 + degree * Math.Asin(bottomportion);
                        startangle_270_360 = 360 - degree * Math.Asin(bottomportion);
                    }

                    //Top right
                    if (r <= cornerdistance_topright)
                    {
                        if (startangle_0_90 < cornerangle_topright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (startangle_0_90 + angleAxis.Offset), (cornerangle_topright + angleAxis.Offset));
                        }
                        if (cornerangle_topright < endangle_0_90)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, (cornerangle_topright + angleAxis.Offset), (endangle_0_90 + angleAxis.Offset));
                        }
                    }

                    //Top left
                    if (r <= cornerdistance_topleft)
                    {
                        if (startangle_90_180 < cornerangle_topleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_90_180 + angleAxis.Offset, cornerangle_topleft + angleAxis.Offset);
                        }
                        if (cornerangle_topleft < endangle_90_180)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_topleft + angleAxis.Offset, endangle_90_180 + angleAxis.Offset);
                        }
                    }

                    //Bottom left
                    if (r <= cornerdistance_bottomleft)
                    {
                        if (startangle_180_270 < cornerangle_bottomleft)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_180_270 + angleAxis.Offset, cornerangle_bottomleft + angleAxis.Offset);
                        }
                        if (cornerangle_bottomleft < endangle_180_270)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomleft + angleAxis.Offset, endangle_180_270 + angleAxis.Offset);
                        }
                    }

                    //Bottom right
                    if (r <= cornerdistance_bottomright)
                    {
                        if (startangle_270_360 < cornerangle_bottomright)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, startangle_270_360 + angleAxis.Offset, cornerangle_bottomright + angleAxis.Offset);
                        }
                        if (cornerangle_bottomright < endangle_270_360)
                        {
                            this.RenderTickArc(axis, angleAxis, tickValue, pen, cornerangle_bottomright + angleAxis.Offset, endangle_270_360 + angleAxis.Offset);
                        }
                    }
                }
            }

            if (pass == 1)
            {
                foreach (double tickValue in textticks)
                {
                    this.RenderTickText(axis, tickValue, angleAxis);
                }
            }
        }