/// <summary> /// Builds isoline data for 2d scalar field contained in data source. /// </summary> /// <returns>Collection of data describing built isolines.</returns> public IsolineCollection BuildIsoline() { VerifyDataSource(); segments = new IsolineCollection(); minMax = (double.IsNaN(missingValue) ? dataSource.GetMinMax() : dataSource.GetMinMax(missingValue)); segments.Min = minMax.Min; segments.Max = minMax.Max; if (!minMax.IsEmpty) { values = dataSource.Data; double[] levels = GetLevelsForIsolines(); foreach (double level in levels) { PrepareCells(level); } if (segments.Lines.Count > 0 && segments.Lines[segments.Lines.Count - 1].OtherPoints.Count == 0) { segments.Lines.RemoveAt(segments.Lines.Count - 1); } } return(segments); }
private IEnumerable <double> GetAdditionalIsolines(IsolineCollection collection) { var dataSource = DataSource; var visibleMinMax = dataSource.GetMinMax(Plotter2D.Visible); var visibleMinMaxRatio = (collection.Max - collection.Min) / visibleMinMax.GetLength(); var log = Math.Log10(visibleMinMaxRatio); if (log > 0.9) { var upperLog = Math.Ceiling(log); var divisionsNum = Math.Pow(10, upperLog); var delta = (collection.Max - collection.Min) / divisionsNum; var start = Math.Ceiling(visibleMinMax.Min / delta) * delta; var x = start; while (x < visibleMinMax.Max) { yield return(x); x += delta; } } }
protected IEnumerable <double> GetAdditionalLevels(IsolineCollection collection) { var dataSource = DataSource; var visibleMinMax = dataSource.GetMinMax(Plotter2D.Visible); double totalDelta = collection.Max - collection.Min; double visibleMinMaxRatio = totalDelta / visibleMinMax.GetLength(); double defaultDelta = totalDelta / 12; if (true || 2 * defaultDelta < visibleMinMaxRatio) { double number = Math.Ceiling(visibleMinMaxRatio * 4); number = Math.Pow(2, Math.Ceiling(Math.Log(number) / Math.Log(2))); double delta = totalDelta / number; double x = collection.Min + Math.Ceiling((visibleMinMax.Min - collection.Min) / delta) * delta; List <double> result = new List <double>(); while (x < visibleMinMax.Max) { result.Add(x); x += delta; } return(result); } return(Enumerable.Empty <double>()); }
/// <summary> /// Annotates the specified isoline collection. /// </summary> /// <param name="collection">The collection.</param> /// <param name="visible">The visible rectangle.</param> /// <returns></returns> public Collection <IsolineTextLabel> Annotate(IsolineCollection collection, DataRect visible) { Collection <IsolineTextLabel> res = new Collection <IsolineTextLabel>(); foreach (var line in collection.Lines) { double way = 0; var forwardSegments = line.GetSegments(); using (var forwardEnumerator = forwardSegments.GetEnumerator()) { forwardEnumerator.MoveNext(); foreach (var segment in line.GetSegments()) { bool hasForwardSegment = forwardEnumerator.MoveNext(); double length = segment.GetLength(); way += length; if (way > wayBeforeText) { way = 0; var rotation = (segment.Max - segment.Min).ToAngle(); if (hasForwardSegment) { var forwardSegment = forwardEnumerator.Current; rotation = (rotation + (forwardSegment.Max - forwardSegment.Min).ToAngle()) / 2; } res.Add(new IsolineTextLabel { Value = line.RealValue, Position = segment.Max, Rotation = rotation }); } } } } return(res); }
private void RenderLabels(DrawingContext dc, IsolineCollection collection) { if (Plotter2D == null) { return; } if (collection == null) { return; } if (!DrawLabels) { return; } var viewportBounds = ViewportPanel.GetViewportBounds(this); if (viewportBounds.IsEmpty) { return; } var strokeThickness = StrokeThickness; var visible = Plotter2D.Visible; var output = Plotter2D.Viewport.Output; var transform = Plotter2D.Transform.WithRects(viewportBounds, new Rect(RenderSize)); var labelStringFormat = LabelStringFormat; // drawing constants var labelRectangleFill = Brushes.White; var biggerViewport = viewportBounds.ZoomOutFromCenter(1.1); // getting and filtering annotations to draw only visible ones Annotater.WayBeforeText = Math.Sqrt(visible.Width * visible.Width + visible.Height * visible.Height) / 100 * WayBeforeTextMultiplier; var annotations = Annotater.Annotate(collection, visible) .Where(annotation => { Point viewportPosition = annotation.Position.DataToViewport(transform); return(biggerViewport.Contains(viewportPosition)); }); // drawing annotations foreach (var annotation in annotations) { FormattedText text = CreateFormattedText(annotation.Value.ToString(LabelStringFormat)); Point position = annotation.Position.DataToScreen(transform); var labelTransform = CreateTransform(annotation, text, position); // creating rectange stroke double colorRatio = (annotation.Value - collection.Min) / (collection.Max - collection.Min); colorRatio = MathHelper.Clamp(colorRatio); Color rectangleStrokeColor = Palette.GetColor(colorRatio); SolidColorBrush rectangleStroke = new SolidColorBrush(rectangleStrokeColor); Pen labelRectangleStrokePen = new Pen(rectangleStroke, 2); dc.PushTransform(labelTransform); { var bounds = RectExtensions.FromCenterSize(position, new Size(text.Width, text.Height)); bounds = bounds.ZoomOutFromCenter(1.3); dc.DrawRoundedRectangle(labelRectangleFill, labelRectangleStrokePen, bounds, 8, 8); DrawTextInPosition(dc, text, position); } dc.Pop(); } }
protected void RenderIsolineCollection(DrawingContext dc, double strokeThickness, IsolineCollection collection, CoordinateTransform transform) { foreach (LevelLine line in collection) { StreamGeometry lineGeometry = new StreamGeometry(); using (var context = lineGeometry.Open()) { context.BeginFigure(line.StartPoint.ViewportToScreen(transform), false, false); if (!UseBezierCurves) { context.PolyLineTo(line.OtherPoints.ViewportToScreen(transform).ToArray(), true, true); } else { context.PolyBezierTo(BezierBuilder.GetBezierPoints(line.AllPoints.ViewportToScreen(transform).ToArray()).Skip(1).ToArray(), true, true); } } lineGeometry.Freeze(); Pen pen = new Pen(new SolidColorBrush(Palette.GetColor(line.Value01)), strokeThickness); dc.DrawGeometry(null, pen, lineGeometry); } }