Exemple #1
0
        /// <summary>
        /// Renders the transformed points as a line (smoothed if <see cref="InterpolationAlgorithm"/> isn’t <c>null</c>) and markers (if <see cref="MarkerType"/> is not <c>None</c>).
        /// </summary>
        /// <param name="rc">The render context.</param>
        /// <param name="clippingRect">The clipping rectangle.</param>
        /// <param name="pointsToRender">The points to render.</param>
        protected virtual void RenderLineAndMarkers(IRenderContext rc, OxyRect clippingRect, IList <ScreenPoint> pointsToRender)
        {
            var screenPoints = pointsToRender;

            if (this.InterpolationAlgorithm != null)
            {
                // spline smoothing (should only be used on small datasets)
                var resampledPoints = ScreenPointHelper.ResamplePoints(pointsToRender, this.MinimumSegmentLength);
                screenPoints = this.InterpolationAlgorithm.CreateSpline(resampledPoints, false, 0.25);
            }

            // clip the line segments with the clipping rectangle
            if (this.StrokeThickness > 0 && this.ActualLineStyle != LineStyle.None)
            {
                this.RenderLine(rc, clippingRect, screenPoints);
            }

            if (this.MarkerType != MarkerType.None)
            {
                var markerBinOffset = this.MarkerResolution > 0 ? this.Transform(this.MinX, this.MinY) : default(ScreenPoint);

                rc.DrawMarkers(
                    clippingRect,
                    pointsToRender,
                    this.MarkerType,
                    this.MarkerOutline,
                    new[] { this.MarkerSize },
                    this.ActualMarkerFill,
                    this.MarkerStroke,
                    this.MarkerStrokeThickness,
                    this.EdgeRenderingMode,
                    this.MarkerResolution,
                    markerBinOffset);
            }
        }
Exemple #2
0
        /// <summary>
        /// Renders a chunk of points on the screen.
        /// </summary>
        /// <param name="context">Render context.</param>
        /// <param name="points">Screen points.</param>
        /// <returns>The list of resampled points.</returns>
        protected virtual List <ScreenPoint> RenderScreenPoints(AreaRenderContext context, List <ScreenPoint> points)
        {
            var final = points;

            if (context.Reverse)
            {
                final.Reverse();
            }

            if (this.InterpolationAlgorithm != null)
            {
                var resampled = ScreenPointHelper.ResamplePoints(final, this.MinimumSegmentLength);
                final = this.InterpolationAlgorithm.CreateSpline(resampled, false, 0.25);
            }

            context.RenderContext.DrawClippedLine(
                context.ClippingRect,
                final,
                context.MinDistSquared,
                this.GetSelectableColor(context.Color),
                this.StrokeThickness,
                this.EdgeRenderingMode,
                context.DashArray,
                this.LineJoin);

            return(final);
        }
        public void ResamplePoints()
        {
            var points = CreatePointList();
            var result = ScreenPointHelper.ResamplePoints(points, 1);

            Assert.AreEqual(4, result.Count);
        }
        protected void RenderLine(IRenderContext rc, OxyRect clippingRect, IList <ScreenPoint> pointsToRender, OxyColor lineColor, double strokeness, LineStyle lineStyle)
        {
            //var screenPoints = pointsToRender;
            var resampledPoints = ScreenPointHelper.ResamplePoints(pointsToRender, 2);
            //screenPoints = CreateSpline(resampledPoints, 0.5, null, false, 0.25);

            var outputBuffer = new List <ScreenPoint>(pointsToRender.Count);

            if (this.LineStyle == LineStyle.None)
            {
                foreach (ScreenPoint sp in pointsToRender)
                {
                    rc.DrawMarker(clippingRect, sp, MarkerType.Diamond, null, 3, lineColor, lineColor, 1);
                }
            }
            else
            {
                var dash_array = lineStyle.GetDashArray();
                rc.DrawClippedLine(
                    clippingRect,
                    pointsToRender,
                    0,
                    lineColor,
                    strokeness,
                    dash_array,
                    LineJoin.Round,
                    false,
                    outputBuffer);
            }
        }
        /// <summary>
        /// Renders the transformed points.
        /// </summary>
        /// <param name="rc">
        /// The render context.
        /// </param>
        /// <param name="clippingRect">
        /// The clipping rectangle.
        /// </param>
        /// <param name="pointsToRender">
        /// The points to render.
        /// </param>
        protected void RenderPoints(IRenderContext rc, OxyRect clippingRect, IList <ScreenPoint> pointsToRender)
        {
            var screenPoints = pointsToRender;

            if (this.Smooth)
            {
                // spline smoothing (should only be used on small datasets)
                var resampledPoints = ScreenPointHelper.ResamplePoints(pointsToRender, this.MinimumSegmentLength);
                screenPoints = CanonicalSplineHelper.CreateSpline(resampledPoints, 0.5, null, false, 0.25);
            }

            // clip the line segments with the clipping rectangle
            if (this.StrokeThickness > 0 && this.ActualLineStyle != LineStyle.None)
            {
                this.RenderSmoothedLine(rc, clippingRect, screenPoints);
            }

            if (this.MarkerType != MarkerType.None)
            {
                rc.DrawMarkers(
                    pointsToRender,
                    clippingRect,
                    this.MarkerType,
                    this.MarkerOutline,
                    new[] { this.MarkerSize },
                    this.MarkerFill,
                    this.MarkerStroke,
                    this.MarkerStrokeThickness);
            }
        }
Exemple #6
0
        /// <summary>
        /// Renders a chunk of points on the screen.
        /// </summary>
        /// <param name="context">Render context.</param>
        /// <param name="points">Screen points.</param>
        /// <returns>The list of resampled points.</returns>
        protected virtual List <ScreenPoint> RenderScreenPoints(AreaRenderContext context, List <ScreenPoint> points)
        {
            var final = points;

            if (context.Reverse)
            {
                final.Reverse();
            }

            if (this.Smooth)
            {
                var resampled = ScreenPointHelper.ResamplePoints(final, this.MinimumSegmentLength);
                final = CanonicalSplineHelper.CreateSpline(resampled, 0.5, null, false, 0.25);
            }

            context.RenderContext.DrawClippedLine(
                context.ClippingRect,
                final,
                context.MinDistSquared,
                this.GetSelectableColor(context.Color),
                this.StrokeThickness,
                context.DashArray,
                this.LineJoin,
                false);

            return(final);
        }
        public void GetCentroid()
        {
            var points   = CreatePointList();
            var centroid = ScreenPointHelper.GetCentroid(points);

            Assert.AreEqual(0.041666, centroid.X, 1e-6);
            Assert.AreEqual(0.708333, centroid.Y, 1e-6);
        }
Exemple #8
0
        protected TrackerHitResult MyGetNearestInterpolatedPointInternal(List <DataPoint> points, ScreenPoint point)
        {
            if (this.XAxis == null || this.YAxis == null || points == null)
            {
                return(null);
            }

            var    spn   = default(ScreenPoint);
            var    dpn   = default(DataPoint);
            double index = -1;

            double minimumDistance = double.MaxValue;

            for (int i = 0; i + 1 < points.Count; i++)
            {
                var p1 = points[i];
                var p2 = points[i + 1];
                if (!this.IsValidPoint(p1) || !this.IsValidPoint(p2))
                {
                    continue;
                }

                var sp1 = this.Transform(p1);
                var sp2 = this.Transform(p2);

                // Find the nearest point on the line segment.
                var spl = ScreenPointHelper.FindPointOnLine(point, sp1, sp2);

                if (ScreenPoint.IsUndefined(spl))
                {
                    // P1 && P2 coincident
                    continue;
                }

                double l2 = (point - spl).LengthSquared;

                if (l2 < minimumDistance)
                {
                    double segmentLength = (sp2 - sp1).Length;
                    double u             = segmentLength > 0 ? (spl - sp1).Length / segmentLength : 0;
                    dpn             = new DataPoint(p1.X + (u * (p2.X - p1.X)), p1.Y + (u * (p2.Y - p1.Y)));
                    spn             = spl;
                    minimumDistance = l2;
                    index           = i + u;
                }
            }

            if (minimumDistance < double.MaxValue)
            {
                object item = this.GetItem((int)index);
                return(new MySignalTrackerHitResult(ParentControl, this, dpn, spn, item)
                {
                    Index = index
                });
            }

            return(null);
        }
Exemple #9
0
        /// <summary>
        /// Gets the point on the series that is nearest the specified point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c>.</param>
        /// <returns>A TrackerHitResult for the current hit.</returns>
        public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate)
        {
            var points = this.Points;

            if (points == null)
            {
                return(null);
            }

            var    spn   = default(ScreenPoint);
            var    dpn   = default(DataPoint);
            double index = -1;

            double minimumDistance = double.MaxValue;

            for (int i = 0; i + 1 < points.Count; i += 2)
            {
                var p1 = points[i];
                var p2 = points[i + 1];
                if (!this.IsValidPoint(p1) || !this.IsValidPoint(p2))
                {
                    continue;
                }

                var sp1 = this.Transform(p1);
                var sp2 = this.Transform(p2);

                // Find the nearest point on the line segment.
                var spl = ScreenPointHelper.FindPointOnLine(point, sp1, sp2);

                if (ScreenPoint.IsUndefined(spl))
                {
                    // P1 && P2 coincident
                    continue;
                }

                double l2 = (point - spl).LengthSquared;

                if (l2 < minimumDistance)
                {
                    double u = (spl - sp1).Length / (sp2 - sp1).Length;
                    dpn             = new DataPoint(p1.X + (u * (p2.X - p1.X)), p1.Y + (u * (p2.Y - p1.Y)));
                    spn             = spl;
                    minimumDistance = l2;
                    index           = i + u;
                }
            }

            if (minimumDistance < double.MaxValue)
            {
                return(new TrackerHitResult(this, dpn, spn, this.GetItem((int)index))
                {
                    Index = index
                });
            }

            return(null);
        }
Exemple #10
0
        protected override HitTestResult HitTestOverride(HitTestArguments args)
        {
            if (this.actualBounds == null)
            {
                return(null);
            }

            return(ScreenPointHelper.IsPointInPolygon(args.Point, this.actualBounds) ? new HitTestResult(this, args.Point) : null);
        }
        /// <summary>
        /// Tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="point">
        /// The point.
        /// </param>
        /// <param name="tolerance">
        /// The tolerance.
        /// </param>
        /// <returns>
        /// A hit test result.
        /// </returns>
        protected internal override HitTestResult HitTest(ScreenPoint point, double tolerance)
        {
            if (this.actualBounds == null)
            {
                return(null);
            }

            // Todo: see if performance can be improved by checking rectangle (with rotation and alignment), not polygon
            return(ScreenPointHelper.IsPointInPolygon(point, this.actualBounds) ? new HitTestResult(point) : null);
        }
Exemple #12
0
        /// <summary>
        /// When overridden in a derived class, tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="args">The hit test arguments.</param>
        /// <returns>
        /// The result of the hit test.
        /// </returns>
        protected override HitTestResult HitTestOverride(HitTestArguments args)
        {
            if (this.actualBounds == null)
            {
                return(null);
            }

            // Todo: see if performance can be improved by checking rectangle (with rotation and alignment), not polygon
            return(ScreenPointHelper.IsPointInPolygon(args.Point, this.actualBounds) ? new HitTestResult(this, args.Point) : null);
        }
Exemple #13
0
        /// <summary>
        /// When overridden in a derived class, tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="args">The hit test arguments.</param>
        /// <returns>
        /// The result of the hit test.
        /// </returns>
        protected override HitTestResult HitTestOverride(HitTestArguments args)
        {
            if (this.screenPoints == null)
            {
                // Points not specified.
                return(null);
            }

            return(ScreenPointHelper.IsPointInPolygon(args.Point, this.screenPoints) ? new HitTestResult(this, args.Point) : null);
        }
Exemple #14
0
        /// <summary>
        /// Gets the screen points.
        /// </summary>
        /// <returns>The list of points to display on screen for this path.</returns>
        protected override IList <ScreenPoint> GetScreenPoints()
        {
            var screenPoints = this.Points.Select(this.Transform).ToList();

            if (this.InterpolationAlgorithm != null)
            {
                var resampledPoints = ScreenPointHelper.ResamplePoints(screenPoints, this.MinimumSegmentLength);
                return(this.InterpolationAlgorithm.CreateSpline(resampledPoints, false, 0.25));
            }

            return(this.Points.Select(this.Transform).ToList());
        }
Exemple #15
0
        /// <summary>
        /// Gets the screen points.
        /// </summary>
        /// <returns>The list of points to display on screen for this path.</returns>
        protected override IList <ScreenPoint> GetScreenPoints()
        {
            var screenPoints = this.Points.Select(this.Transform).ToList();

            if (this.Smooth)
            {
                var resampledPoints = ScreenPointHelper.ResamplePoints(screenPoints, this.MinimumSegmentLength);
                return(CanonicalSplineHelper.CreateSpline(resampledPoints, 0.5, null, false, 0.25));
            }

            return(this.Points.Select(this.Transform).ToList());
        }
Exemple #16
0
        /// <summary>
        /// When overridden in a derived class, tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="args">The hit test arguments.</param>
        /// <returns>
        /// The result of the hit test.
        /// </returns>
        protected override HitTestResult HitTestOverride(HitTestArguments args)
        {
            var    nearestPoint = ScreenPointHelper.FindNearestPointOnPolyline(args.Point, this.screenPoints);
            double dist         = (args.Point - nearestPoint).Length;

            if (dist < args.Tolerance)
            {
                return(new HitTestResult(this, nearestPoint));
            }

            return(null);
        }
Exemple #17
0
        /// <summary>
        /// Tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="tolerance">The tolerance.</param>
        /// <returns>
        /// A hit test result.
        /// </returns>
        protected internal override HitTestResult HitTest(ScreenPoint point, double tolerance)
        {
            var    nearestPoint = ScreenPointHelper.FindNearestPointOnPolyline(point, this.screenPoints);
            double dist         = (point - nearestPoint).Length;

            if (dist < tolerance)
            {
                return(new HitTestResult(nearestPoint));
            }

            return(null);
        }
        protected void RenderUnClippedLine(IRenderContext rc, IList <ScreenPoint> pointsToRender, OxyColor lineColor, double strokeness, LineStyle lineStyle)
        {
            var screenPoints    = pointsToRender;
            var resampledPoints = ScreenPointHelper.ResamplePoints(pointsToRender, 2);

            screenPoints = CreateSpline(resampledPoints, 0.5, null, false, 0.25);

            var outputBuffer = new List <ScreenPoint>(pointsToRender.Count);

            var dash_array = lineStyle.GetDashArray();

            rc.DrawLine(pointsToRender, lineColor, strokeness, dash_array, LineJoin.Round, false);
        }
Exemple #19
0
        /// <summary>
        /// Gets the point on the series that is nearest the specified point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c>.</param>
        /// <returns>A TrackerHitResult for the current hit.</returns>
        public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate)
        {
            if (this.XAxis == null || this.YAxis == null)
            {
                return(null);
            }

            if (interpolate)
            {
                return(null);
            }

            TrackerHitResult result = null;

            // http://paulbourke.net/geometry/pointlineplane/
            double minimumDistance = double.MaxValue;
            var    points          = this.ActualPoints;

            for (int i = 0; i < points.Count; i++)
            {
                var p1        = points[i];
                var basePoint = new DataPoint(p1.X, this.Base);
                var sp1       = this.Transform(p1);
                var sp2       = this.Transform(basePoint);
                var u         = ScreenPointHelper.FindPositionOnLine(point, sp1, sp2);

                if (double.IsNaN(u))
                {
                    continue;
                }

                if (u < 0 || u > 1)
                {
                    continue; // outside line
                }

                var    sp       = sp1 + ((sp2 - sp1) * u);
                double distance = (point - sp).LengthSquared;

                if (distance < minimumDistance)
                {
                    result = new TrackerHitResult(
                        this, new DataPoint(p1.X, p1.Y), new ScreenPoint(sp1.x, sp1.y), this.GetItem(i));
                    minimumDistance = distance;
                }
            }

            return(result);
        }
        /// <summary>
        /// Renders the polygon annotation.
        /// </summary>
        /// <param name="rc">The render context.</param>
        public override void Render(IRenderContext rc)
        {
            base.Render(rc);
            if (this.Points == null)
            {
                return;
            }

            // transform to screen coordinates
            this.screenPoints = this.Points.Select(this.Transform).ToList();
            if (this.screenPoints.Count == 0)
            {
                return;
            }

            // clip to the area defined by the axes
            var clippingRectangle = this.GetClippingRect();

            const double MinimumSegmentLength = 4;

            rc.DrawClippedPolygon(
                clippingRectangle,
                this.screenPoints,
                MinimumSegmentLength * MinimumSegmentLength,
                this.GetSelectableFillColor(this.Fill),
                this.GetSelectableColor(this.Stroke),
                this.StrokeThickness,
                this.EdgeRenderingMode,
                this.LineStyle,
                this.LineJoin);

            if (!string.IsNullOrEmpty(this.Text))
            {
                this.GetActualTextAlignment(out var ha, out var va);
                var textPosition = this.GetActualTextPosition(() => ScreenPointHelper.GetCentroid(this.screenPoints));

                rc.DrawClippedText(
                    clippingRectangle,
                    textPosition,
                    this.Text,
                    this.ActualTextColor,
                    this.ActualFont,
                    this.ActualFontSize,
                    this.ActualFontWeight,
                    this.TextRotation,
                    ha,
                    va);
            }
        }
Exemple #21
0
        /// <summary>
        /// Renders the polygon 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);
            if (this.Points == null)
            {
                return;
            }

            // transform to screen coordinates
            this.screenPoints = this.Points.Select(p => this.Transform(p)).ToList();
            if (this.screenPoints.Count == 0)
            {
                return;
            }

            // clip to the area defined by the axes
            var clipping = this.GetClippingRect();

            const double MinimumSegmentLength = 4;

            rc.DrawClippedPolygon(
                this.screenPoints,
                clipping,
                MinimumSegmentLength * MinimumSegmentLength,
                this.GetSelectableFillColor(this.Fill),
                this.GetSelectableColor(this.Color),
                this.StrokeThickness,
                this.LineStyle,
                this.LineJoin);

            if (!string.IsNullOrEmpty(this.Text))
            {
                var textPosition = ScreenPointHelper.GetCentroid(this.screenPoints);

                rc.DrawClippedText(
                    clipping,
                    textPosition,
                    this.Text,
                    this.ActualTextColor,
                    this.ActualFont,
                    this.ActualFontSize,
                    this.ActualFontWeight,
                    0,
                    HorizontalAlignment.Center,
                    VerticalAlignment.Middle);
            }
        }
Exemple #22
0
        protected override void RenderLineAndMarkers(IRenderContext rc, OxyRect clippingRect, IList <ScreenPoint> pointsToRender)
        {
            if (Smooth)
            {
                pointsToRender = CatmullRomSplineHelper.CreateSpline(ScreenPointHelper.ResamplePoints(pointsToRender, MinimumSegmentLength), 0.5,
                                                                     0.25 / _smoothessMultipler);
            }

            if (StrokeThickness > 0.0 && ActualLineStyle != LineStyle.None)
            {
                RenderLine(rc, clippingRect, pointsToRender);
            }

            if (MarkerType != MarkerType.None)
            {
                var binOffset = MarkerResolution > 0 ? Transform(MinX, MinY) : new ScreenPoint();
                rc.DrawMarkers(clippingRect, pointsToRender, MarkerType, MarkerOutline, new[] { MarkerSize }, ActualMarkerFill, MarkerStroke,
                               MarkerStrokeThickness, MarkerResolution, binOffset);
            }
        }
        /// <summary>
        /// Tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="point">
        /// The point.
        /// </param>
        /// <param name="tolerance">
        /// The tolerance.
        /// </param>
        /// <returns>
        /// A hit test result.
        /// </returns>
        protected internal override HitTestResult HitTest(ScreenPoint point, double tolerance)
        {
            if ((point - this.screenStartPoint).Length < tolerance)
            {
                return(new HitTestResult(this.screenStartPoint, null, 1));
            }

            if ((point - this.screenEndPoint).Length < tolerance)
            {
                return(new HitTestResult(this.screenEndPoint, null, 2));
            }

            var p = ScreenPointHelper.FindPointOnLine(point, this.screenStartPoint, this.screenEndPoint);

            if ((p - point).Length < tolerance)
            {
                return(new HitTestResult(p));
            }

            return(null);
        }
Exemple #24
0
        /// <summary>
        /// Gets the point on the series that is nearest the specified point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c> .</param>
        /// <returns>A TrackerHitResult for the current hit.</returns>
        public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate)
        {
            for (int i = 0; i < this.slicePoints.Count; i++)
            {
                if (ScreenPointHelper.IsPointInPolygon(point, this.slicePoints[i]))
                {
                    var slice = this.slices[i];
                    var item  = this.GetItem(i);
                    return(new TrackerHitResult
                    {
                        Series = this,
                        Position = point,
                        Item = item,
                        Index = i,
                        Text = StringHelper.Format(this.ActualCulture, this.TrackerFormatString, slice, this.Title, slice.Label, slice.Value, slice.Value / this.total)
                    });
                }
            }

            return(null);
        }
Exemple #25
0
        /// <summary>
        /// When overridden in a derived class, tests if the plot element is hit by the specified point.
        /// </summary>
        /// <param name="args">The hit test arguments.</param>
        /// <returns>
        /// The result of the hit test.
        /// </returns>
        protected override HitTestResult HitTestOverride(HitTestArguments args)
        {
            if ((args.Point - this.screenStartPoint).Length < args.Tolerance)
            {
                return(new HitTestResult(this, this.screenStartPoint, null, 1));
            }

            if ((args.Point - this.screenEndPoint).Length < args.Tolerance)
            {
                return(new HitTestResult(this, this.screenEndPoint, null, 2));
            }

            var p = ScreenPointHelper.FindPointOnLine(args.Point, this.screenStartPoint, this.screenEndPoint);

            if ((p - args.Point).Length < args.Tolerance)
            {
                return(new HitTestResult(this, p));
            }

            return(null);
        }
Exemple #26
0
        /// <summary>
        /// Gets the point on the curve that is nearest the specified point.
        /// </summary>
        /// <param name="points">The point list.</param>
        /// <param name="startIdx">The index to start from.</param>
        /// <param name="point">The point.</param>
        /// <returns>A tracker hit result if a point was found.</returns>
        /// <remarks>The Text property of the result will not be set, since the formatting depends on the various series.</remarks>
        protected TrackerHitResult GetNearestInterpolatedPointInternal(List <DataPoint> points, int startIdx, ScreenPoint point)
        {
            if (this.XAxis == null || this.YAxis == null || points == null)
            {
                return(null);
            }

            var    spn   = default(ScreenPoint);
            var    dpn   = default(DataPoint);
            double index = -1;

            double minimumDistance = double.MaxValue;

            for (int i = startIdx; i + 1 < points.Count; i++)
            {
                var p1 = points[i];
                var p2 = points[i + 1];
                if (!this.IsValidPoint(p1) || !this.IsValidPoint(p2))
                {
                    continue;
                }

                var sp1 = this.Transform(p1);
                var sp2 = this.Transform(p2);

                // Find the nearest point on the line segment.
                var spl = ScreenPointHelper.FindPointOnLine(point, sp1, sp2);

                if (ScreenPoint.IsUndefined(spl))
                {
                    // P1 && P2 coincident
                    continue;
                }

                double l2 = (point - spl).LengthSquared;

                if (l2 < minimumDistance)
                {
                    double segmentLength = (sp2 - sp1).Length;
                    double u             = segmentLength > 0 ? (spl - sp1).Length / segmentLength : 0;
                    dpn             = this.InverseTransform(spl);
                    spn             = spl;
                    minimumDistance = l2;
                    index           = i + u;
                }
            }

            if (minimumDistance < double.MaxValue)
            {
                var item = this.GetItem((int)Math.Round(index));
                return(new TrackerHitResult
                {
                    Series = this,
                    DataPoint = dpn,
                    Position = spn,
                    Item = item,
                    Index = index
                });
            }

            return(null);
        }
Exemple #27
0
        /// <summary>
        /// Renders the series on the specified rendering context.
        /// </summary>
        /// <param name="rc">The rendering context.</param>
        /// <param name="model">The owner plot model.</param>
        public override void Render(IRenderContext rc, PlotModel model)
        {
            var actualPoints  = this.ActualPoints;
            var actualPoints2 = this.ActualPoints2;
            int n0            = actualPoints.Count;

            if (n0 == 0)
            {
                return;
            }

            this.VerifyAxes();

            double minDistSquared = this.MinimumSegmentLength * this.MinimumSegmentLength;

            var clippingRect = this.GetClippingRect();

            rc.SetClip(clippingRect);

            // Transform all points to screen coordinates
            IList <ScreenPoint> pts0 = new ScreenPoint[n0];

            for (int i = 0; i < n0; i++)
            {
                pts0[i] = this.XAxis.Transform(actualPoints[i].X, actualPoints[i].Y, this.YAxis);
            }

            int n1 = actualPoints2.Count;
            IList <ScreenPoint> pts1 = new ScreenPoint[n1];

            for (int i = 0; i < n1; i++)
            {
                int j = this.Reverse2 ? n1 - 1 - i : i;
                pts1[j] = this.XAxis.Transform(actualPoints2[i].X, actualPoints2[i].Y, this.YAxis);
            }

            if (this.Smooth)
            {
                var rpts0 = ScreenPointHelper.ResamplePoints(pts0, this.MinimumSegmentLength);
                var rpts1 = ScreenPointHelper.ResamplePoints(pts1, this.MinimumSegmentLength);

                pts0 = CanonicalSplineHelper.CreateSpline(rpts0, 0.5, null, false, 0.25);
                pts1 = CanonicalSplineHelper.CreateSpline(rpts1, 0.5, null, false, 0.25);
            }

            var dashArray = this.ActualDashArray;

            // draw the clipped lines
            rc.DrawClippedLine(
                clippingRect,
                pts0,
                minDistSquared,
                this.GetSelectableColor(this.ActualColor),
                this.StrokeThickness,
                dashArray,
                this.LineJoin,
                false);
            rc.DrawClippedLine(
                clippingRect,
                pts1,
                minDistSquared,
                this.GetSelectableColor(this.ActualColor2),
                this.StrokeThickness,
                dashArray,
                this.LineJoin,
                false);

            // combine the two lines and draw the clipped area
            var pts = new List <ScreenPoint>();

            pts.AddRange(pts1);
            pts.AddRange(pts0);

            // pts = SutherlandHodgmanClipping.ClipPolygon(clippingRect, pts);
            rc.DrawClippedPolygon(clippingRect, pts, minDistSquared, this.GetSelectableFillColor(this.ActualFill), OxyColors.Undefined);

            var markerSizes = new[] { this.MarkerSize };

            // draw the markers on top
            rc.DrawMarkers(
                clippingRect,
                pts0,
                this.MarkerType,
                null,
                markerSizes,
                this.MarkerFill,
                this.MarkerStroke,
                this.MarkerStrokeThickness,
                1);
            rc.DrawMarkers(
                clippingRect,
                pts1,
                this.MarkerType,
                null,
                markerSizes,
                this.MarkerFill,
                this.MarkerStroke,
                this.MarkerStrokeThickness,
                1);

            rc.ResetClip();
        }
Exemple #28
0
        /// <summary>
        /// Renders data points from the specified index to the specified maximum x, skipping NaN values.
        /// </summary>
        /// <param name="actualPoints">Points list.</param>
        /// <param name="chunksOfPoints">A list where chunks will be placed.</param>
        /// <param name="startIndex">The start index of the points to render.</param>
        /// <param name="maximumX">The maximum X coordinate to render.</param>
        /// <param name="rc">Render context</param>
        /// <param name="clippingRect">Clipping rectangle.</param>
        /// <param name="minDistSquared">Minimal distance squared.</param>
        /// <param name="reverse">Reverse points.</param>
        /// <param name="color">Stroke color.</param>
        private void RenderChunkedPoints(List <DataPoint> actualPoints, List <List <ScreenPoint> > chunksOfPoints, int startIndex, double maximumX, IRenderContext rc, OxyRect clippingRect, double minDistSquared, bool reverse, OxyColor color)
        {
            var dashArray    = this.ActualDashArray;
            var screenPoints = new List <ScreenPoint>();

            Action <List <ScreenPoint> > finalizeChunk = list =>
            {
                var final = list;

                if (reverse)
                {
                    final.Reverse();
                }

                if (this.Smooth)
                {
                    var resampled = ScreenPointHelper.ResamplePoints(final, this.MinimumSegmentLength);
                    final = CanonicalSplineHelper.CreateSpline(resampled, 0.5, null, false, 0.25);
                }

                chunksOfPoints.Add(final);

                rc.DrawClippedLine(
                    clippingRect,
                    final,
                    minDistSquared,
                    this.GetSelectableColor(color),
                    this.StrokeThickness,
                    dashArray,
                    this.LineJoin,
                    false);
            };

            int clipCount = 0;

            for (int i = startIndex; i < actualPoints.Count; i++)
            {
                var point = actualPoints[i];

                if (double.IsNaN(point.Y))
                {
                    if (screenPoints.Count == 0)
                    {
                        continue;
                    }

                    finalizeChunk(screenPoints);
                    screenPoints = new List <ScreenPoint>();
                }
                else
                {
                    var sp = this.XAxis.Transform(point.X, point.Y, this.YAxis);
                    screenPoints.Add(sp);
                }

                // We break after two points were seen beyond xMax to ensure glitch-free rendering.
                clipCount += point.x > maximumX ? 1 : 0;
                if (clipCount > 1)
                {
                    break;
                }
            }

            if (screenPoints.Count > 0)
            {
                finalizeChunk(screenPoints);
            }
        }
Exemple #29
0
        /// <summary>
        /// Gets the nearest point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="interpolate">interpolate if set to <c>true</c> .</param>
        /// <returns>A TrackerHitResult for the current hit.</returns>
        public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate)
        {
            if (this.XAxis == null || this.YAxis == null)
            {
                return(null);
            }

            double minimumDistance = double.MaxValue;
            var    result          = new TrackerHitResult(this, DataPoint.Undefined, ScreenPoint.Undefined);

            foreach (var item in this.Items)
            {
                foreach (var outlier in item.Outliers)
                {
                    var    sp = this.Transform(item.X, outlier);
                    double d  = (sp - point).LengthSquared;
                    if (d < minimumDistance)
                    {
                        result.DataPoint = new DataPoint(item.X, outlier);
                        result.Position  = sp;
                        result.Item      = item;
                        result.Text      = this.Format(
                            this.OutlierTrackerFormatString,
                            item,
                            this.Title,
                            this.XAxis.GetValue(result.DataPoint.X),
                            outlier);
                        minimumDistance = d;
                    }
                }

                // check if we are inside the box rectangle
                var rect = this.GetBoxRect(item);
                if (rect.Contains(point))
                {
                    result.DataPoint = new DataPoint(item.X, this.YAxis.InverseTransform(point.Y));
                    result.Position  = this.Transform(result.DataPoint);
                    result.Item      = item;

                    result.Text = this.Format(
                        this.TrackerFormatString,
                        item,
                        this.Title,
                        this.XAxis.GetValue(result.DataPoint.X),
                        item.UpperWhisker,
                        item.BoxTop,
                        item.Median,
                        item.BoxBottom,
                        item.LowerWhisker);

                    minimumDistance = 0;
                }

                var topWhisker    = this.Transform(item.X, item.UpperWhisker);
                var bottomWhisker = this.Transform(item.X, item.LowerWhisker);

                // check if we are near the line
                var    p  = ScreenPointHelper.FindPointOnLine(point, topWhisker, bottomWhisker);
                double d2 = (p - point).LengthSquared;
                if (d2 < minimumDistance)
                {
                    result.DataPoint = this.InverseTransform(p);
                    result.Position  = this.Transform(result.DataPoint);
                    result.Item      = item;
                    result.Text      = this.Format(
                        this.TrackerFormatString,
                        item,
                        this.Title,
                        this.XAxis.GetValue(result.DataPoint.X),
                        item.UpperWhisker,
                        item.BoxTop,
                        item.Median,
                        item.BoxBottom,
                        item.LowerWhisker);
                    minimumDistance = d2;
                }
            }

            if (minimumDistance < double.MaxValue)
            {
                return(result);
            }

            return(null);
        }
Exemple #30
0
        /// <summary>
        /// Gets the nearest point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="interpolate">interpolate if set to <c>true</c> .</param>
        /// <returns>A TrackerHitResult for the current hit.</returns>
        public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate)
        {
            if (this.XAxis == null || this.YAxis == null)
            {
                return(null);
            }

            double           minimumDistance = double.MaxValue;
            TrackerHitResult result          = null;

            foreach (var item in this.ActualItems)
            {
                foreach (var outlier in item.Outliers)
                {
                    var    sp = this.Transform(item.X, outlier);
                    double d  = (sp - point).LengthSquared;
                    if (d < minimumDistance)
                    {
                        result = new TrackerHitResult
                        {
                            Series    = this,
                            DataPoint = new DataPoint(item.X, outlier),
                            Position  = sp,
                            Item      = item,
                            Text      =
                                StringHelper.Format(
                                    this.ActualCulture,
                                    this.OutlierTrackerFormatString,
                                    item,
                                    this.Title,
                                    this.XAxis.Title ?? DefaultXAxisTitle,
                                    this.XAxis.GetValue(item.X),
                                    outlier)
                        };
                        minimumDistance = d;
                    }
                }

                var hitPoint = DataPoint.Undefined;

                // check if we are inside the box rectangle
                var rect = this.GetBoxRect(item);
                if (rect.Contains(point))
                {
                    hitPoint        = new DataPoint(item.X, this.YAxis.InverseTransform(point.Y));
                    minimumDistance = 0;
                }

                var topWhisker    = this.Transform(item.X, item.UpperWhisker);
                var bottomWhisker = this.Transform(item.X, item.LowerWhisker);

                // check if we are near the line
                var    p  = ScreenPointHelper.FindPointOnLine(point, topWhisker, bottomWhisker);
                double d2 = (p - point).LengthSquared;
                if (d2 < minimumDistance)
                {
                    hitPoint        = this.InverseTransform(p);
                    minimumDistance = d2;
                }

                if (hitPoint.IsDefined())
                {
                    result = new TrackerHitResult
                    {
                        Series    = this,
                        DataPoint = hitPoint,
                        Position  = this.Transform(hitPoint),
                        Item      = item,
                        Text      =
                            StringHelper.Format(
                                this.ActualCulture,
                                this.TrackerFormatString,
                                item,
                                this.Title,
                                this.XAxis.Title ?? DefaultXAxisTitle,
                                this.XAxis.GetValue(item.X),
                                this.YAxis.GetValue(item.UpperWhisker),
                                this.YAxis.GetValue(item.BoxTop),
                                this.YAxis.GetValue(item.Median),
                                this.YAxis.GetValue(item.BoxBottom),
                                this.YAxis.GetValue(item.LowerWhisker),
                                this.YAxis.GetValue(item.Mean))
                    };
                }
            }

            if (minimumDistance < double.MaxValue)
            {
                return(result);
            }

            return(null);
        }