示例#1
0
        public void IsInside()
        {
            var clipping = new CohenSutherlandClipping(0, 1, 0, 1);

            Assert.IsTrue(clipping.IsInside(0.5, 0.5));
            Assert.IsFalse(clipping.IsInside(-0.5, 0.5));
        }
 public void EndpointsOutsideArea2()
 {
     var clipping = new CohenSutherlandClipping(new OxyRect(0.3, -0.5, 0.5, 1));
     var p0 = new ScreenPoint(0, 0);
     var p1 = new ScreenPoint(1, 0);
     Assert.IsTrue(clipping.ClipLine(ref p0, ref p1));
     Assert.AreEqual(new ScreenPoint(0.3, 0), p0);
     Assert.AreEqual(new ScreenPoint(0.8, 0), p1);
 }
 public void EndpointsOutsideArea()
 {
     var clipping = new CohenSutherlandClipping(new OxyRect(0, 0, 1, 1));
     var p0 = new ScreenPoint(0.3, -0.2);
     var p1 = new ScreenPoint(0.6, 1.3);
     Assert.IsTrue(clipping.ClipLine(ref p0, ref p1));
     Assert.AreEqual(0, p0.Y);
     Assert.AreEqual(1, p1.Y);
 }
 public void ClipLine_EndpointsInsideArea()
 {
     var clipping = new CohenSutherlandClipping(0, 1, 0, 1);
     var p0 = new ScreenPoint(0.3, 0.2);
     var p1 = new ScreenPoint(0.6, 0.8);
     Assert.IsTrue(clipping.ClipLine(ref p0, ref p1));
     Assert.AreEqual(0.2, p0.Y);
     Assert.AreEqual(0.8, p1.Y);
 }
 public void ClipLine_LineOutsideArea()
 {
     var clipping = new CohenSutherlandClipping(0, 1, 0, 1);
     var p0 = new ScreenPoint(0.3, -0.2);
     var p1 = new ScreenPoint(0.6, -0.2);
     Assert.IsFalse(clipping.ClipLine(ref p0, ref p1));
     Assert.AreEqual(-0.2, p0.Y);
     Assert.AreEqual(-0.2, p1.Y);
 }
            public void LineOutsideArea()
            {
                var clipping = new CohenSutherlandClipping(new OxyRect(0, 0, 1, 1));
                var p0       = new ScreenPoint(0.3, -0.2);
                var p1       = new ScreenPoint(0.6, -0.2);

                Assert.IsFalse(clipping.ClipLine(ref p0, ref p1));
                Assert.AreEqual(-0.2, p0.Y);
                Assert.AreEqual(-0.2, p1.Y);
            }
示例#7
0
        public void ClipLine_EndpointsOutsideArea()
        {
            var clipping = new CohenSutherlandClipping(0, 1, 0, 1);
            var p0       = new ScreenPoint(0.3, -0.2);
            var p1       = new ScreenPoint(0.6, 1.3);

            Assert.IsTrue(clipping.ClipLine(ref p0, ref p1));
            Assert.AreEqual(0, p0.Y);
            Assert.AreEqual(1, p1.Y);
        }
            public void EndpointsOutsideArea2()
            {
                var clipping = new CohenSutherlandClipping(new OxyRect(0.3, -0.5, 0.5, 1));
                var p0       = new ScreenPoint(0, 0);
                var p1       = new ScreenPoint(1, 0);

                Assert.IsTrue(clipping.ClipLine(ref p0, ref p1));
                Assert.AreEqual(new ScreenPoint(0.3, 0), p0);
                Assert.AreEqual(new ScreenPoint(0.8, 0), p1);
            }
            public void EndpointsInsideArea()
            {
                var clipping = new CohenSutherlandClipping(new OxyRect(0, 0, 1, 1));
                var p0       = new ScreenPoint(0.3, 0.2);
                var p1       = new ScreenPoint(0.6, 0.8);

                Assert.IsTrue(clipping.ClipLine(ref p0, ref p1));
                Assert.AreEqual(0.2, p0.Y);
                Assert.AreEqual(0.8, p1.Y);
            }
            public void OutsidePoint()
            {
                var clipping = new CohenSutherlandClipping(new OxyRect(0, 0, 1, 1));

                Assert.IsFalse(clipping.IsInside(new ScreenPoint(-0.5, 0.5)));
            }
 public void OutsidePoint()
 {
     var clipping = new CohenSutherlandClipping(new OxyRect(0, 0, 1, 1));
     Assert.IsFalse(clipping.IsInside(new ScreenPoint(-0.5, 0.5)));
 }
示例#12
0
        /// <summary>
        /// Renders the annotation on the specified context.
        /// </summary>
        /// <param name="rc">The render context.</param>
        public override void Render(IRenderContext rc)
        {
            base.Render(rc);

            this.CalculateActualMinimumsMaximums();

            this.screenPoints = this.GetScreenPoints();

            var clippingRectangle = this.GetClippingRect();

            const double MinimumSegmentLength = 4;

            var clippedPoints = new List <ScreenPoint>();
            var dashArray     = this.LineStyle.GetDashArray();

            if (this.StrokeThickness > 0 && this.LineStyle != LineStyle.None)
            {
                rc.DrawClippedLine(
                    clippingRectangle,
                    this.screenPoints,
                    MinimumSegmentLength * MinimumSegmentLength,
                    this.GetSelectableColor(this.Color),
                    this.StrokeThickness,
                    dashArray,
                    this.LineJoin,
                    this.Aliased,
                    null,
                    clippedPoints.AddRange);
            }

            var margin = this.TextMargin;

            this.GetActualTextAlignment(out var ha, out var va);

            if (ha == HorizontalAlignment.Center)
            {
                margin = 0;
            }
            else
            {
                margin *= this.TextLinePosition < 0.5 ? 1 : -1;
            }

            if (GetPointAtRelativeDistance(clippedPoints, this.TextLinePosition, margin, out var position, out var angle))
            {
                if (angle < -90)
                {
                    angle += 180;
                }

                if (angle > 90)
                {
                    angle -= 180;
                }

                switch (this.TextOrientation)
                {
                case AnnotationTextOrientation.Horizontal:
                    angle = 0;
                    break;

                case AnnotationTextOrientation.Vertical:
                    angle = -90;
                    break;
                }

                // Apply 'padding' to the position
                var angleInRadians = angle / 180 * Math.PI;
                var f = 1;

                if (ha == HorizontalAlignment.Right)
                {
                    f = -1;
                }

                if (ha == HorizontalAlignment.Center)
                {
                    f = 0;
                }

                position += new ScreenVector(f * this.TextPadding * Math.Cos(angleInRadians), f * this.TextPadding * Math.Sin(angleInRadians));

                if (!string.IsNullOrEmpty(this.Text))
                {
                    var textPosition = this.GetActualTextPosition(() => position);

                    if (this.TextPosition.IsDefined())
                    {
                        angle = this.TextRotation;
                    }

                    if (this.ClipText)
                    {
                        var cs = new CohenSutherlandClipping(clippingRectangle);
                        if (cs.IsInside(position))
                        {
                            rc.DrawClippedText(
                                clippingRectangle,
                                textPosition,
                                this.Text,
                                this.ActualTextColor,
                                this.ActualFont,
                                this.ActualFontSize,
                                this.ActualFontWeight,
                                angle,
                                this.TextHorizontalAlignment,
                                this.TextVerticalAlignment);
                        }
                    }
                    else
                    {
                        rc.DrawText(
                            textPosition,
                            this.Text,
                            this.ActualTextColor,
                            this.ActualFont,
                            this.ActualFontSize,
                            this.ActualFontWeight,
                            angle,
                            ha,
                            va);
                    }
                }
            }
        }
示例#13
0
        /// <summary>
        /// Renders the annotation on the specified context.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="model">The model.</param>
        public override void Render(IRenderContext rc, PlotModel model)
        {
            base.Render(rc, model);

            this.CalculateActualMinimumsMaximums();

            this.screenPoints = this.GetScreenPoints();

            // clip to the area defined by the axes
            var clippingRectangle = OxyRect.Create(
                this.ClipByXAxis ? this.XAxis.ScreenMin.X : PlotModel.PlotArea.Left,
                this.ClipByYAxis ? this.YAxis.ScreenMin.Y : PlotModel.PlotArea.Top,
                this.ClipByXAxis ? this.XAxis.ScreenMax.X : PlotModel.PlotArea.Right,
                this.ClipByYAxis ? this.YAxis.ScreenMax.Y : PlotModel.PlotArea.Bottom);

            const double MinimumSegmentLength = 4;

            var clippedPoints = new List <ScreenPoint>();
            var dashArray     = this.LineStyle.GetDashArray();

            rc.DrawClippedLine(
                clippingRectangle,
                this.screenPoints,
                MinimumSegmentLength * MinimumSegmentLength,
                this.GetSelectableColor(this.Color),
                this.StrokeThickness,
                dashArray,
                this.LineJoin,
                this.aliased,
                null,
                clippedPoints.AddRange);

            ScreenPoint position;
            double      angle;
            double      margin = this.TextMargin;

            if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
            {
                margin = 0;
            }
            else
            {
                margin *= this.TextLinePosition < 0.5 ? 1 : -1;
            }

            if (GetPointAtRelativeDistance(clippedPoints, this.TextLinePosition, margin, out position, out angle))
            {
                if (angle < -90)
                {
                    angle += 180;
                }

                if (angle > 90)
                {
                    angle -= 180;
                }

                switch (this.TextOrientation)
                {
                case AnnotationTextOrientation.Horizontal:
                    angle = 0;
                    break;

                case AnnotationTextOrientation.Vertical:
                    angle = -90;
                    break;
                }

                // Apply 'padding' to the position
                var angleInRadians = angle / 180 * Math.PI;
                var f = 1;

                if (this.TextHorizontalAlignment == HorizontalAlignment.Right)
                {
                    f = -1;
                }

                if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
                {
                    f = 0;
                }

                position += new ScreenVector(f * this.TextPadding * Math.Cos(angleInRadians), f * this.TextPadding * Math.Sin(angleInRadians));

                if (!string.IsNullOrEmpty(this.Text))
                {
                    var textPosition = this.GetActualTextPosition(() => position);

                    if (this.TextPosition.IsDefined())
                    {
                        angle = this.TextRotation;
                    }

                    if (this.ClipText)
                    {
                        var cs = new CohenSutherlandClipping(clippingRectangle);
                        if (cs.IsInside(position))
                        {
                            rc.DrawClippedText(
                                clippingRectangle,
                                textPosition,
                                this.Text,
                                this.ActualTextColor,
                                this.ActualFont,
                                this.ActualFontSize,
                                this.ActualFontWeight,
                                angle,
                                this.TextHorizontalAlignment,
                                this.TextVerticalAlignment);
                        }
                    }
                    else
                    {
                        rc.DrawText(
                            textPosition,
                            this.Text,
                            this.ActualTextColor,
                            this.ActualFont,
                            this.ActualFontSize,
                            this.ActualFontWeight,
                            angle,
                            this.TextHorizontalAlignment,
                            this.TextVerticalAlignment);
                    }
                }
            }
        }
示例#14
0
        /// <summary>
        /// Renders the line annotation.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="model">
        /// The plot model.
        /// </param>
        public override void Render(IRenderContext rc, PlotModel model)
        {
            base.Render(rc, model);

            bool aliased = false;

            double actualMinimumX = Math.Max(this.MinimumX, this.XAxis.ActualMinimum);
            double actualMaximumX = Math.Min(this.MaximumX, this.XAxis.ActualMaximum);
            double actualMinimumY = Math.Max(this.MinimumY, this.YAxis.ActualMinimum);
            double actualMaximumY = Math.Min(this.MaximumY, this.YAxis.ActualMaximum);

            if (!this.ClipByXAxis)
            {
                double right = XAxis.InverseTransform(PlotModel.PlotArea.Right);
                double left  = XAxis.InverseTransform(PlotModel.PlotArea.Left);
                actualMaximumX = Math.Max(left, right);
                actualMinimumX = Math.Min(left, right);
            }

            if (!this.ClipByYAxis)
            {
                double bottom = YAxis.InverseTransform(PlotModel.PlotArea.Bottom);
                double top    = YAxis.InverseTransform(PlotModel.PlotArea.Top);
                actualMaximumY = Math.Max(top, bottom);
                actualMinimumY = Math.Min(top, bottom);
            }

            // y=f(x)
            Func <double, double> fx = null;

            // x=f(y)
            Func <double, double> fy = null;

            switch (this.Type)
            {
            case LineAnnotationType.Horizontal:
                fx = x => this.Y;
                break;

            case LineAnnotationType.Vertical:
                fy = y => this.X;
                break;

            case LineAnnotationType.EquationY:
                fx = this.Equation;
                break;

            case LineAnnotationType.EquationX:
                fy = this.Equation;
                break;

            default:
                fx = x => (this.Slope * x) + this.Intercept;
                break;
            }

            var points = new List <DataPoint>();

            bool isCurvedLine = !(this.XAxis is LinearAxis) || !(this.YAxis is LinearAxis) || this.Type == LineAnnotationType.EquationY;

            if (!isCurvedLine)
            {
                // we only need to calculate two points if it is a straight line
                if (fx != null)
                {
                    points.Add(new DataPoint(actualMinimumX, fx(actualMinimumX)));
                    points.Add(new DataPoint(actualMaximumX, fx(actualMaximumX)));
                }
                else if (fy != null)
                {
                    points.Add(new DataPoint(fy(actualMinimumY), actualMinimumY));
                    points.Add(new DataPoint(fy(actualMaximumY), actualMaximumY));
                }

                if (this.Type == LineAnnotationType.Horizontal || this.Type == LineAnnotationType.Vertical)
                {
                    // use aliased line drawing for horizontal and vertical lines
                    aliased = true;
                }
            }
            else
            {
                if (fx != null)
                {
                    double x = actualMinimumX;

                    // todo: the step size should be adaptive
                    double dx = (actualMaximumX - actualMinimumX) / 100;
                    while (true)
                    {
                        points.Add(new DataPoint(x, fx(x)));
                        if (x > actualMaximumX)
                        {
                            break;
                        }

                        x += dx;
                    }
                }
                else if (fy != null)
                {
                    double y = actualMinimumY;

                    // todo: the step size should be adaptive
                    double dy = (actualMaximumY - actualMinimumY) / 100;
                    while (true)
                    {
                        points.Add(new DataPoint(fy(y), y));
                        if (y > actualMaximumY)
                        {
                            break;
                        }

                        y += dy;
                    }
                }
            }

            // transform to screen coordinates
            this.screenPoints = points.Select(p => this.Transform(p)).ToList();

            // clip to the area defined by the axes
            var clippingRectangle = OxyRect.Create(
                this.ClipByXAxis ? this.XAxis.ScreenMin.X : PlotModel.PlotArea.Left,
                this.ClipByYAxis ? this.YAxis.ScreenMin.Y : PlotModel.PlotArea.Top,
                this.ClipByXAxis ? this.XAxis.ScreenMax.X : PlotModel.PlotArea.Right,
                this.ClipByYAxis ? this.YAxis.ScreenMax.Y : PlotModel.PlotArea.Bottom);

            const double MinimumSegmentLength = 4;

            IList <ScreenPoint> clippedPoints = null;

            rc.DrawClippedLine(
                this.screenPoints,
                clippingRectangle,
                MinimumSegmentLength * MinimumSegmentLength,
                this.GetSelectableColor(this.Color),
                this.StrokeThickness,
                this.LineStyle,
                this.LineJoin,
                aliased,
                pts => clippedPoints = pts);

            ScreenPoint position;
            double      angle;
            double      margin = this.TextMargin;

            if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
            {
                margin = 0;
            }
            else
            {
                margin *= this.TextPosition < 0.5 ? 1 : -1;
            }

            if (clippedPoints != null && GetPointAtRelativeDistance(clippedPoints, this.TextPosition, margin, out position, out angle))
            {
                if (angle < -90)
                {
                    angle += 180;
                }

                if (angle > 90)
                {
                    angle -= 180;
                }

                switch (this.TextOrientation)
                {
                case AnnotationTextOrientation.Horizontal:
                    angle = 0;
                    break;

                case AnnotationTextOrientation.Vertical:
                    angle = -90;
                    break;
                }

                // Apply 'padding' to the position
                var angleInRadians = angle / 180 * Math.PI;
                var f = 1;

                if (this.TextHorizontalAlignment == HorizontalAlignment.Right)
                {
                    f = -1;
                }

                if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
                {
                    f = 0;
                }

                position.X += f * this.TextPadding * Math.Cos(angleInRadians);
                position.Y += f * this.TextPadding * Math.Sin(angleInRadians);

                var cs = new CohenSutherlandClipping(clippingRectangle);
                if (!string.IsNullOrEmpty(this.Text) && cs.IsInside(position))
                {
                    rc.DrawClippedText(
                        clippingRectangle,
                        position,
                        this.Text,
                        this.ActualTextColor,
                        this.ActualFont,
                        this.ActualFontSize,
                        this.ActualFontWeight,
                        angle,
                        this.TextHorizontalAlignment,
                        this.TextVerticalAlignment);
                }
            }
        }
示例#15
0
        public Point3DCollection CreatePositions(
            Point3D center,
            double radius,
            double startAngle,
            double endAngle,
            double thetadiv    = 32,
            double thickness   = 1.0,
            double depthOffset = 0.0,
            CohenSutherlandClipping clipping = null
            )
        {
            var halfThickness = thickness * 0.5;
            var spoints       = new Point3DCollection();

            for (int i = 0; i <= thetadiv; i++)
            {
                double x = radius * Math.Sin(i * (endAngle - startAngle) / thetadiv + startAngle) + center.X;
                double y = radius * Math.Cos(i * (endAngle - startAngle) / thetadiv + startAngle) + center.Y;
                spoints.Add(new Point3D(x, y, center.Z));
            }


            var segmentCount = spoints.Count - 1;

            var positions = new Point3DCollection(segmentCount * 4);

            for (int i = 0; i < segmentCount; i++)
            {
                //   int startIndex = i * 2;

                var startPoint = spoints[i];
                var endPoint   = spoints[i + 1];

                // Transform the start and end points to screen space
                var s0 = (Point4D)startPoint * this.visualToScreen;
                var s1 = (Point4D)endPoint * this.visualToScreen;

                if (clipping != null)
                {
                    // Apply a clipping rectangle
                    var x0 = s0.X / s0.W;
                    var y0 = s0.Y / s0.W;
                    var x1 = s1.X / s1.W;
                    var y1 = s1.Y / s1.W;

                    if (!clipping.ClipLine(ref x0, ref y0, ref x1, ref y1))
                    {
                        continue;
                    }

                    s0.X = x0 * s0.W;
                    s0.Y = y0 * s0.W;
                    s1.X = x1 * s1.W;
                    s1.Y = y1 * s1.W;
                }

                var lx = (s1.X / s1.W) - (s0.X / s0.W);
                var ly = (s1.Y / s1.W) - (s0.Y / s0.W);
                var l2 = (lx * lx) + (ly * ly);

                var p00 = s0;
                var p01 = s0;
                var p10 = s1;
                var p11 = s1;

                if (l2.Equals(0))
                {
                    // coinciding points (in world space or screen space)
                    var dz = halfThickness;

                    // TODO: make a square with the thickness as side length
                    p00.X -= dz * p00.W;
                    p00.Y -= dz * p00.W;

                    p01.X -= dz * p01.W;
                    p01.Y += dz * p01.W;

                    p10.X += dz * p10.W;
                    p10.Y -= dz * p10.W;

                    p11.X += dz * p11.W;
                    p11.Y += dz * p11.W;
                }
                else
                {
                    var m = halfThickness / Math.Sqrt(l2);

                    // the normal (dx,dy)
                    var dx = -ly * m;
                    var dy = lx * m;

                    // segment start points
                    p00.X += dx * p00.W;
                    p00.Y += dy * p00.W;
                    p01.X -= dx * p01.W;
                    p01.Y -= dy * p01.W;

                    // segment end points
                    p10.X += dx * p10.W;
                    p10.Y += dy * p10.W;
                    p11.X -= dx * p11.W;
                    p11.Y -= dy * p11.W;
                }

                if (!depthOffset.Equals(0))
                {
                    // Adjust the z-coordinate by the depth offset
                    p00.Z -= depthOffset;
                    p01.Z -= depthOffset;
                    p10.Z -= depthOffset;
                    p11.Z -= depthOffset;

                    // Transform from screen space to world space
                    p00 *= this.screenToVisual;
                    p01 *= this.screenToVisual;
                    p10 *= this.screenToVisual;
                    p11 *= this.screenToVisual;

                    positions.Add(new Point3D(p00.X / p00.W, p00.Y / p00.W, p00.Z / p00.W));
                    positions.Add(new Point3D(p01.X / p00.W, p01.Y / p01.W, p01.Z / p01.W));
                    positions.Add(new Point3D(p10.X / p00.W, p10.Y / p10.W, p10.Z / p10.W));
                    positions.Add(new Point3D(p11.X / p00.W, p11.Y / p11.W, p11.Z / p11.W));
                }
                else
                {
                    // Transform from screen space to world space
                    p00 *= this.screenToVisual;
                    p01 *= this.screenToVisual;
                    p10 *= this.screenToVisual;
                    p11 *= this.screenToVisual;

                    positions.Add(new Point3D(p00.X, p00.Y, p00.Z));
                    positions.Add(new Point3D(p01.X, p01.Y, p01.Z));
                    positions.Add(new Point3D(p10.X, p10.Y, p10.Z));
                    positions.Add(new Point3D(p11.X, p11.Y, p11.Z));
                }
            }

            positions.Freeze();
            return(positions);
            //  return null;
        }
示例#16
0
        /// <summary>
        /// Renders the annotation on the specified context.
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="model">The model.</param>
        public override void Render(IRenderContext rc, PlotModel model)
        {
            base.Render(rc, model);

            this.CalculateActualMinimumsMaximums();

            this.screenPoints = this.GetScreenPoints();

            // clip to the area defined by the axes
            var clippingRectangle = OxyRect.Create(
                this.ClipByXAxis ? this.XAxis.ScreenMin.X : PlotModel.PlotArea.Left,
                this.ClipByYAxis ? this.YAxis.ScreenMin.Y : PlotModel.PlotArea.Top,
                this.ClipByXAxis ? this.XAxis.ScreenMax.X : PlotModel.PlotArea.Right,
                this.ClipByYAxis ? this.YAxis.ScreenMax.Y : PlotModel.PlotArea.Bottom);

            const double MinimumSegmentLength = 4;

            var clippedPoints = new List<ScreenPoint>();
            var dashArray = this.LineStyle.GetDashArray();

            rc.DrawClippedLine(
               clippingRectangle,
               this.screenPoints,
               MinimumSegmentLength * MinimumSegmentLength,
               this.GetSelectableColor(this.Color),
               this.StrokeThickness,
               dashArray,
               this.LineJoin,
               this.aliased,
               null,
               clippedPoints.AddRange);

            ScreenPoint position;
            double angle;
            double margin = this.TextMargin;

            if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
            {
                margin = 0;
            }
            else
            {
                margin *= this.TextLinePosition < 0.5 ? 1 : -1;
            }

            if (GetPointAtRelativeDistance(clippedPoints, this.TextLinePosition, margin, out position, out angle))
            {
                if (angle < -90)
                {
                    angle += 180;
                }

                if (angle > 90)
                {
                    angle -= 180;
                }

                switch (this.TextOrientation)
                {
                    case AnnotationTextOrientation.Horizontal:
                        angle = 0;
                        break;
                    case AnnotationTextOrientation.Vertical:
                        angle = -90;
                        break;
                }

                // Apply 'padding' to the position
                var angleInRadians = angle / 180 * Math.PI;
                var f = 1;

                if (this.TextHorizontalAlignment == HorizontalAlignment.Right)
                {
                    f = -1;
                }

                if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
                {
                    f = 0;
                }

                position += new ScreenVector(f * this.TextPadding * Math.Cos(angleInRadians), f * this.TextPadding * Math.Sin(angleInRadians));

                if (!string.IsNullOrEmpty(this.Text))
                {
                    var textPosition = this.GetActualTextPosition(() => position);
                    
                    if (this.TextPosition.IsDefined())
                    {
                        angle = this.TextRotation;
                    }

                    if (this.ClipText)
                    {
                        var cs = new CohenSutherlandClipping(clippingRectangle);
                        if (cs.IsInside(position))
                        {
                            rc.DrawClippedText(
                                clippingRectangle,
                                textPosition,
                                this.Text,
                                this.ActualTextColor,
                                this.ActualFont,
                                this.ActualFontSize,
                                this.ActualFontWeight,
                                angle,
                                this.TextHorizontalAlignment,
                                this.TextVerticalAlignment);
                        }
                    }
                    else
                    {
                        rc.DrawText(
                           textPosition,
                           this.Text,
                           this.ActualTextColor,
                           this.ActualFont,
                           this.ActualFontSize,
                           this.ActualFontWeight,
                           angle,
                           this.TextHorizontalAlignment,
                           this.TextVerticalAlignment);
                    }
                }
            }
        }
示例#17
0
        /// <summary>
        /// Renders the line annotation.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="model">
        /// The plot model.
        /// </param>
        public override void Render(IRenderContext rc, PlotModel model)
        {
            base.Render(rc, model);

            bool aliased = false;

            double actualMinimumX = Math.Max(this.MinimumX, this.XAxis.ActualMinimum);
            double actualMaximumX = Math.Min(this.MaximumX, this.XAxis.ActualMaximum);
            double actualMinimumY = Math.Max(this.MinimumY, this.YAxis.ActualMinimum);
            double actualMaximumY = Math.Min(this.MaximumY, this.YAxis.ActualMaximum);

            if (!this.ClipByXAxis)
            {
                double right = XAxis.InverseTransform(PlotModel.PlotArea.Right);
                double left = XAxis.InverseTransform(PlotModel.PlotArea.Left);
                actualMaximumX = Math.Max(left, right);
                actualMinimumX = Math.Min(left, right);
            }

            if (!this.ClipByYAxis)
            {
                double bottom = YAxis.InverseTransform(PlotModel.PlotArea.Bottom);
                double top = YAxis.InverseTransform(PlotModel.PlotArea.Top);
                actualMaximumY = Math.Max(top, bottom);
                actualMinimumY = Math.Min(top, bottom);
            }

            // y=f(x)
            Func<double, double> fx = null;

            // x=f(y)
            Func<double, double> fy = null;

            switch (this.Type)
            {
                case LineAnnotationType.Horizontal:
                    fx = x => this.Y;
                    break;
                case LineAnnotationType.Vertical:
                    fy = y => this.X;
                    break;
                case LineAnnotationType.EquationY:
                    fx = this.Equation;
                    break;
                case LineAnnotationType.EquationX:
                    fy = this.Equation;
                    break;
                default:
                    fx = x => (this.Slope * x) + this.Intercept;
                    break;
            }

            var points = new List<DataPoint>();

            bool isCurvedLine = !(this.XAxis is LinearAxis) || !(this.YAxis is LinearAxis) || this.Type == LineAnnotationType.EquationY;

            if (!isCurvedLine)
            {
                // we only need to calculate two points if it is a straight line
                if (fx != null)
                {
                    points.Add(new DataPoint(actualMinimumX, fx(actualMinimumX)));
                    points.Add(new DataPoint(actualMaximumX, fx(actualMaximumX)));
                }
                else if (fy != null)
                {
                    points.Add(new DataPoint(fy(actualMinimumY), actualMinimumY));
                    points.Add(new DataPoint(fy(actualMaximumY), actualMaximumY));
                }

                if (this.Type == LineAnnotationType.Horizontal || this.Type == LineAnnotationType.Vertical)
                {
                    // use aliased line drawing for horizontal and vertical lines
                    aliased = true;
                }
            }
            else
            {
                if (fx != null)
                {
                    double x = actualMinimumX;

                    // todo: the step size should be adaptive
                    double dx = (actualMaximumX - actualMinimumX) / 100;
                    while (true)
                    {
                        points.Add(new DataPoint(x, fx(x)));
                        if (x > actualMaximumX)
                        {
                            break;
                        }

                        x += dx;
                    }
                }
                else if (fy != null)
                {
                    double y = actualMinimumY;

                    // todo: the step size should be adaptive
                    double dy = (actualMaximumY - actualMinimumY) / 100;
                    while (true)
                    {
                        points.Add(new DataPoint(fy(y), y));
                        if (y > actualMaximumY)
                        {
                            break;
                        }

                        y += dy;
                    }
                }
            }

            // transform to screen coordinates
            this.screenPoints = points.Select(p => this.Transform(p)).ToList();

            // clip to the area defined by the axes
            var clippingRectangle = OxyRect.Create(
                this.ClipByXAxis ? this.XAxis.ScreenMin.X : PlotModel.PlotArea.Left,
                this.ClipByYAxis ? this.YAxis.ScreenMin.Y : PlotModel.PlotArea.Top,
                this.ClipByXAxis ? this.XAxis.ScreenMax.X : PlotModel.PlotArea.Right,
                this.ClipByYAxis ? this.YAxis.ScreenMax.Y : PlotModel.PlotArea.Bottom);

            const double MinimumSegmentLength = 4;

            IList<ScreenPoint> clippedPoints = null;

            rc.DrawClippedLine(
               this.screenPoints,
               clippingRectangle,
               MinimumSegmentLength * MinimumSegmentLength,
               this.GetSelectableColor(this.Color),
               this.StrokeThickness,
               this.LineStyle,
                this.LineJoin,
                aliased,
                pts => clippedPoints = pts);

            ScreenPoint position;
            double angle;
            double margin = this.TextMargin;

            if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
            {
                margin = 0;
            }
            else
            {
                margin *= this.TextPosition < 0.5 ? 1 : -1;
            }

            if (clippedPoints != null && GetPointAtRelativeDistance(clippedPoints, this.TextPosition, margin, out position, out angle))
            {
                if (angle < -90)
                {
                    angle += 180;
                }

                if (angle > 90)
                {
                    angle -= 180;
                }

                switch (this.TextOrientation)
                {
                    case AnnotationTextOrientation.Horizontal:
                        angle = 0;
                        break;
                    case AnnotationTextOrientation.Vertical:
                        angle = -90;
                        break;
                }

                // Apply 'padding' to the position
                var angleInRadians = angle / 180 * Math.PI;
                var f = 1;

                if (this.TextHorizontalAlignment == HorizontalAlignment.Right)
                {
                    f = -1;
                }

                if (this.TextHorizontalAlignment == HorizontalAlignment.Center)
                {
                    f = 0;
                }

                position.X += f * this.TextPadding * Math.Cos(angleInRadians);
                position.Y += f * this.TextPadding * Math.Sin(angleInRadians);

                var cs = new CohenSutherlandClipping(clippingRectangle);
                if (!string.IsNullOrEmpty(this.Text) && cs.IsInside(position))
                {
                    rc.DrawClippedText(
                        clippingRectangle,
                        position,
                        this.Text,
                        this.ActualTextColor,
                        this.ActualFont,
                        this.ActualFontSize,
                        this.ActualFontWeight,
                        angle,
                        this.TextHorizontalAlignment,
                        this.TextVerticalAlignment);
                }
            }
        }
 public void IsInside()
 {
     var clipping = new CohenSutherlandClipping(0, 1, 0, 1);
     Assert.IsTrue(clipping.IsInside(0.5, 0.5));
     Assert.IsFalse(clipping.IsInside(-0.5, 0.5));
 }