/// <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> /// 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> /// 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); }
/// <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); } }
/// <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); }
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); }
/// <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); } } }