Exemple #1
0
        private bool IsZoomEnable(DataRect rect)
        {
            bool res = true;

            if (IsHorizontalNavigationEnabled)
            {
                double e_max = Math.Log(Math.Max(Math.Abs(rect.XMax), Math.Abs(rect.XMin)), 2);
                double log   = Math.Log(rect.Width, 2);
                res = log > e_max - 40;
            }
            if (IsVerticalNavigationEnabled)
            {
                double e_max = Math.Log(Math.Max(Math.Abs(rect.YMax), Math.Abs(rect.YMin)), 2);
                double log   = Math.Log(rect.Height, 2);
                res = res && log > e_max - 40;
            }
            return(res);
        }
Exemple #2
0
        /// <summary>
        /// Sets plot rectangle for current instance of <see cref="PlotBase"/>
        /// </summary>
        /// <param name="plotRect">plot rectangle value that would be set for current instance of <see cref="PlotBase"/></param>
        /// <param name="fromAutoFit">Identifies that it is internal call</param>
        protected void SetPlotRect(DataRect plotRect, bool fromAutoFit)
        {
            IsInternalChange = true;

            EnumAll(p =>
            {
                p.PlotOriginX = fromAutoFit ? plotRect.XMin : p.PlotOriginX;
                p.PlotOriginY = fromAutoFit ? plotRect.YMin : p.PlotOriginY;
                p.PlotWidth   = plotRect.Width;
                p.PlotHeight  = plotRect.Height;
                if (!fromAutoFit)
                {
                    p.IsAutoFitEnabled = false;
                    p.InvalidateMeasure();
                }
            });

            IsInternalChange = false;
        }
Exemple #3
0
 /// <summary>
 /// Positions child elements and determines a size for a <see cref="Figure"/>.
 /// </summary>
 /// <param name="finalSize">The final area within the parent that Figure should use to arrange itself and its children.</param>
 /// <returns>The actual size used.</returns>
 protected override Size ArrangeOverride(Size finalSize)
 {
     finalSize.Width  = Math.Min(finalSize.Width, DesiredSize.Width);
     finalSize.Height = Math.Min(finalSize.Height, DesiredSize.Height);
     // Arranging child elements
     foreach (UIElement elt in Children)
     {
         Image img = elt as Image;
         if (img != null)
         {
             Batch batch = img.Tag as Batch;
             if (batch != null && batch.Image == elt) // Special algorithm for snapshot image
             {
                 DataRect plotRect = batch.PlotRect;
                 var      newLT    = new Point(LeftFromX(plotRect.XMin), TopFromY(plotRect.YMax));
                 var      newRB    = new Point(LeftFromX(plotRect.XMax), TopFromY(plotRect.YMin));
                 batch.Image.Arrange(new Rect(newLT.X, newLT.Y, newRB.X - newLT.X, newRB.Y - newLT.Y));
             }
             else
             {
                 elt.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
             }
         }
         else
         {
             elt.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
         }
     }
     if (ClipToBounds)
     {
         Clip = new RectangleGeometry
         {
             Rect = new Rect(new Point(0, 0), finalSize)
         }
     }
     ;
     else
     {
         Clip = null;
     }
     return(finalSize);
 }
Exemple #4
0
        public void PlotMEMS()
        {
            int i = 0;

            double[] y1   = new double[POINTS];
            double[] y2   = new double[POINTS];
            double[] y3   = new double[POINTS];
            double[] time = new double[POINTS];
            var      lg   = new LineGraph();

            foreach (DataPoint dp in dataQ)
            {
                time[i] = dp._time.ToOADate();
                y1[i]   = dp.d1;
                y2[i]   = dp.d2;
                y3[i++] = dp.d3;
            }
            InteractiveDataDisplay.WPF.DataRect plotRect = new InteractiveDataDisplay.WPF.DataRect(time[0], y1.Min(), time.Max(), y1.Max());
            lg.Plot(time, y1);
            lg.Plot(time, y2);
            lg.Plot(time, y3);
        }
        private void OnTaskCompleted(RenderResult r, RenderTaskState state)
        {
            if (r != null && !state.IsCanceled)
            {

                WriteableBitmap wr = new WriteableBitmap((int)r.Output.Width, (int)r.Output.Height, 96, 96, PixelFormats.Bgra32, null);
                // Calculate the number of bytes per pixel. 
                int bytesPerPixel = (wr.Format.BitsPerPixel + 7) / 8;
                // Stride is bytes per pixel times the number of pixels.
                // Stride is the byte width of a single rectangle row.
                int stride = wr.PixelWidth * bytesPerPixel;
                wr.WritePixels(new Int32Rect(0, 0, wr.PixelWidth, wr.PixelHeight), r.Image, stride, 0);


                outputImage.Source = wr;
                Canvas.SetLeft(outputImage, r.Output.Left);
                Canvas.SetTop(outputImage, r.Output.Top);
                imageCartesianRect = r.Visible;
                imageSize = new Size(r.Output.Width, r.Output.Height);
                outputImage.RenderTransform = null;
            }

            RaiseTaskCompletion(state.Id);

            runningTasks.Remove(state);

            while (tasks.Count > 1)
            {
                long id = tasks.Dequeue();
                RaiseTaskCompletion(id);
            }
            if (tasks.Count > 0 && runningTasks.Count < maxTasks)
            {
                EnqueueTask(tasks.Dequeue());
            }

            InvalidateMeasure();
        }
Exemple #6
0
        /// <summary>
        /// Performs measure algorithm if current instance of <see cref="PlotBase"/> is master
        /// </summary>
        /// <param name="availableSize">Availible size for measure</param>
        /// <returns>Desired size for current plot</returns>
        protected Size PerformAsMaster(Size availableSize)
        {
            if (double.IsNaN(availableSize.Width) ||
                double.IsNaN(availableSize.Height) ||
                double.IsInfinity(availableSize.Width) ||
                double.IsInfinity(availableSize.Height))
            {
                availableSize = new Size(100, 100);
            }
            if (IsMaster)
            {
                DataRect desiredRect;
                if (IsAutoFitEnabled)
                {
                    //desiredRect = PlotRect;//AggregateBounds();
                    //if (desiredRect.IsEmpty)
                    //    desiredRect = new DataRect(0, 0, 1, 1);
                    //desiredRect.X = desiredRect.X.Zoom(0.5);
                    //desiredRect.Y = desiredRect.Y.Zoom(0.5);
                    //SetPlotRect(desiredRect);

                    desiredRect = AggregateBounds();
                    if (desiredRect.IsEmpty)
                    {
                        desiredRect = new DataRect(0, 0, 1, 1);
                    }

                    SetPlotRect(desiredRect, true);
                }
                else // resize
                {
                    desiredRect = PlotRect;
                }
                Fit(desiredRect, availableSize);
            }
            return(availableSize);
        }
Exemple #7
0
        private void DoPan(Point screenStart, Point screenEnd)
        {
            if (masterPlot != null)
            {
                double dx = IsHorizontalNavigationEnabled ?
                            masterPlot.XFromLeft(screenEnd.X) - masterPlot.XFromLeft(screenStart.X) : 0;
                double dy = IsVerticalNavigationEnabled ?
                            masterPlot.YFromTop(screenEnd.Y) - masterPlot.YFromTop(screenStart.Y) : 0;
                var rect = masterPlot.PlotRect;

                ValidateNavigationLimits();
                bool returnToAvailableArea = NeedReturnToAvailableArea(
                    ref rect, NavigationLimitMaxX, NavigationLimitMinX,
                    NavigationLimitMaxY, NavigationLimitMinY);

                if (returnToAvailableArea)
                {
                    masterPlot.SetPlotRect(rect);
                }
                else
                {
                    double width  = rect.Width;
                    double height = rect.Height;

                    var newRect = new DataRect(
                        rect.XMin - dx,
                        rect.YMin - dy,
                        rect.XMin - dx + width,
                        rect.YMin - dy + height);

                    bool xInBounds = NavigationXIsInBounds(newRect, NavigationLimitMaxX, NavigationLimitMinX);
                    bool yInBounds = NavigationYIsInBounds(newRect, NavigationLimitMaxY, NavigationLimitMinY);


                    if (xInBounds && !yInBounds)
                    {
                        newRect = new DataRect(
                            rect.XMin - dx,
                            rect.YMin,
                            rect.XMin - dx + width,
                            rect.YMin + height);
                        yInBounds = true;
                    }
                    else if (!xInBounds && yInBounds)
                    {
                        newRect = new DataRect(
                            rect.XMin,
                            rect.YMin - dy,
                            rect.XMin + width,
                            rect.YMin - dy + height);
                        xInBounds = true;
                    }


                    if (xInBounds && yInBounds)
                    {
                        masterPlot.SetPlotRect(newRect);
                    }
                }

                masterPlot.IsAutoFitEnabled = false;
            }
        }
Exemple #8
0
 /// <summary>
 /// Updates current instance of <see cref="DataRect"/> with minimal DataRect which will contain current DataRect and specified DataRect
 /// </summary>
 /// <param name="rect">DataRect, which will be used for surrond of current instance of <see cref="DataRect"/></param>
 public void Surround(DataRect rect)
 {
     this.x.Surround(rect.X);
     this.y.Surround(rect.Y);
 }
Exemple #9
0
        /// <summary>
        /// Measures the size in layout required for child elements and determines a size for a <see cref="Figure"/>.
        /// </summary>
        /// <param name="availableSize">The available size that this element can give to child elements. Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param>
        /// <returns>The size that this element determines it needs during layout, based on its calculations of child element sizes.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            // Update number of batches
            SyncMarkerViewModels();
            int batchCount = (int)Math.Ceiling(models.Count / (double)MarkersBatchSize);

            while (batches.Count < batchCount)
            {
                var b = new Batch();
                batches.Add(b);
                Children.Add(b.Image);
                Children.Add(b.Panel);
                // Ensure inner plots have the same data transforms
                b.Panel.SetBinding(PlotBase.XDataTransformProperty,
                                   new Binding("XDataTransform")
                {
                    Source = this
                });
                b.Panel.SetBinding(PlotBase.YDataTransformProperty,
                                   new Binding("YDataTransform")
                {
                    Source = this
                });
            }
            availableSize = PerformAsMaster(availableSize);
            // Request redraw of all batches if transform is changed
            if (ScaleX != prevScaleX || ScaleY != prevScaleY || OffsetX != prevOffsetX || OffsetY != prevOffsetY)
            {
                prevScaleX  = ScaleX;
                prevScaleY  = ScaleY;
                prevOffsetX = OffsetX;
                prevOffsetY = OffsetY;
                idleTask.Start();
                plotVersion++;
                foreach (var b in batches)
                {
                    b.ChangedProperties = null; // Update all properties
                    b.Panel.Visibility  = System.Windows.Visibility.Collapsed;
                    b.Image.Visibility  = System.Windows.Visibility.Visible;
                }
            }
            foreach (UIElement elt in Children)
            {
                Image img = elt as Image;
                if (img != null)
                {
                    Batch batch = img.Tag as Batch;
                    if (batch != null && batch.Image == elt) // Special algorithm for snapshot image
                    {
                        DataRect plotRect = batch.PlotRect;
                        var      newLT    = new Point(LeftFromX(plotRect.XMin), TopFromY(plotRect.YMax));
                        var      newRB    = new Point(LeftFromX(plotRect.XMax), TopFromY(plotRect.YMin));
                        batch.Image.Measure(new Size(newRB.X - newLT.X, newRB.Y - newLT.Y));
                    }
                    else
                    {
                        elt.Measure(availableSize);
                    }
                }
                else
                {
                    elt.Measure(availableSize);
                }
            }
            return(availableSize);
        }
Exemple #10
0
        private void KeyboardNavigationKeyDown(object sender, KeyEventArgs e)
        {
            if (masterPlot != null)
            {
                if (e.Key == Key.Up && IsVerticalNavigationEnabled)
                {
                    var rect = masterPlot.PlotRect;
                    ValidateNavigationLimits();
                    bool returnToAvailableArea = NeedReturnToAvailableArea(
                        ref rect, NavigationLimitMaxX, NavigationLimitMinX,
                        NavigationLimitMaxY, NavigationLimitMinY);
                    if (returnToAvailableArea)
                    {
                        masterPlot.SetPlotRect(rect);
                    }
                    else
                    {
                        double dy = rect.Height / 200;

                        var newRect = new DataRect(
                            rect.XMin,
                            rect.YMin - dy,
                            rect.XMin + rect.Width,
                            rect.YMin - dy + rect.Height);

                        if (NavigationYIsInBounds(newRect, NavigationLimitMaxY, NavigationLimitMinY))
                        {
                            masterPlot.SetPlotRect(newRect);
                        }
                    }

                    masterPlot.IsAutoFitEnabled = false;
                    e.Handled = true;
                }
                if (e.Key == Key.Down && IsVerticalNavigationEnabled)
                {
                    var rect = masterPlot.PlotRect;
                    ValidateNavigationLimits();
                    bool returnToAvailableArea = NeedReturnToAvailableArea(
                        ref rect, NavigationLimitMaxX, NavigationLimitMinX,
                        NavigationLimitMaxY, NavigationLimitMinY);
                    if (returnToAvailableArea)
                    {
                        masterPlot.SetPlotRect(rect);
                    }
                    else
                    {
                        double dy = -rect.Height / 200;

                        var newRect = new DataRect(
                            rect.XMin,
                            rect.YMin - dy,
                            rect.XMin + rect.Width,
                            rect.YMin - dy + rect.Height);

                        if (NavigationYIsInBounds(newRect, NavigationLimitMaxY, NavigationLimitMinY))
                        {
                            masterPlot.SetPlotRect(newRect);
                        }
                    }

                    masterPlot.IsAutoFitEnabled = false;
                    e.Handled = true;
                }
                if (e.Key == Key.Right && IsHorizontalNavigationEnabled)
                {
                    var rect = masterPlot.PlotRect;
                    ValidateNavigationLimits();
                    bool returnToAvailableArea = NeedReturnToAvailableArea(
                        ref rect, NavigationLimitMaxX, NavigationLimitMinX,
                        NavigationLimitMaxY, NavigationLimitMinY);
                    if (returnToAvailableArea)
                    {
                        masterPlot.SetPlotRect(rect);
                    }
                    else
                    {
                        double dx = -rect.Width / 200;

                        var newRect = new DataRect(
                            rect.XMin + dx,
                            rect.YMin,
                            rect.XMin + dx + rect.Width,
                            rect.YMin + rect.Height);

                        if (NavigationXIsInBounds(newRect, NavigationLimitMaxX, NavigationLimitMinX))
                        {
                            masterPlot.SetPlotRect(newRect);
                        }
                    }


                    masterPlot.IsAutoFitEnabled = false;
                    e.Handled = true;
                }
                if (e.Key == Key.Left && IsHorizontalNavigationEnabled)
                {
                    var rect = masterPlot.PlotRect;
                    ValidateNavigationLimits();
                    bool returnToAvailableArea = NeedReturnToAvailableArea(
                        ref rect, NavigationLimitMaxX, NavigationLimitMinX,
                        NavigationLimitMaxY, NavigationLimitMinY);
                    if (returnToAvailableArea)
                    {
                        masterPlot.SetPlotRect(rect);
                    }
                    else
                    {
                        double dx = rect.Width / 200;

                        var newRect = new DataRect(
                            rect.XMin + dx,
                            rect.YMin,
                            rect.XMin + dx + rect.Width,
                            rect.YMin + rect.Height);

                        if (NavigationXIsInBounds(newRect, NavigationLimitMaxX, NavigationLimitMinX))
                        {
                            masterPlot.SetPlotRect(newRect);
                        }
                    }


                    masterPlot.IsAutoFitEnabled = false;
                    e.Handled = true;
                }
                if (e.Key == Key.Subtract)
                {
                    DoZoom(1.2);
                    masterPlot.IsAutoFitEnabled = false;
                    e.Handled = true;
                }
                if (e.Key == Key.Add)
                {
                    DoZoom(1 / 1.2);
                    masterPlot.IsAutoFitEnabled = false;
                    e.Handled = true;
                }
                if (e.Key == Key.Home)
                {
                    masterPlot.IsAutoFitEnabled = true;
                    e.Handled = true;
                }
            }
        }
Exemple #11
0
 /// <summary>
 /// Sets plot rectangle for current instance of <see cref="PlotBase"/>
 /// </summary>
 /// <param name="plotRect">plot rectangle value that would be set for current instance of <see cref="PlotBase"/></param>
 public void SetPlotRect(DataRect plotRect)
 {
     SetPlotRect(plotRect, false);
 }
Exemple #12
0
 /// <summary>
 /// Initializes new instance of RenderTaskState class from given coordinate tranform.
 /// </summary>
 public RenderTaskState(DataRect actualPlotRect, Size screenSize)
 {
     ScreenSize     = screenSize;
     ActualPlotRect = actualPlotRect;
 }
Exemple #13
0
 /// <summary>
 /// Initializes new instance of RenderResult class form given parameters.
 /// </summary>
 /// <param name="image">Array of image pixels.</param>
 /// <param name="visible">Visible rect for graph.</param>
 /// <param name="offset">Image start offset.</param>
 /// <param name="width">Image width.</param>
 /// <param name="height">image height.</param>
 public RenderResult(int[] image, DataRect visible, Point offset, double width, double height)
 {
     this.visible = visible;
     this.output  = new Rect(offset, new Size(width, height));
     this.image   = image;
 }
Exemple #14
0
        /// <summary>
        /// Renders frame and returns it as a render result.
        /// </summary>
        /// <param name="state">Render task state for rendering frame.</param>
        /// <returns>Render result of rendered frame.</returns>
        protected override RenderResult RenderFrame(RenderTaskState state)
        {
            if (state == null)
            {
                throw new ArgumentNullException("state");
            }

            if (!state.Bounds.IsEmpty && !state.IsCanceled && data != null)
            {
                //DataRect dataRect = new DataRect(state.Transform.Visible);
                //Rect output = state.Transform.Screen;
                DataRect dataRect = state.ActualPlotRect;
                DataRect output   = new DataRect(0, 0, state.ScreenSize.Width, state.ScreenSize.Height);
                DataRect bounds   = state.Bounds;

                if (dataRect.XMin >= bounds.XMax || dataRect.XMax <= bounds.XMin ||
                    dataRect.YMin >= bounds.YMax || dataRect.YMax <= bounds.YMin)
                {
                    return(null);
                }

                double left  = 0;
                double xmin  = dataRect.XMin;
                double scale = output.Width / dataRect.Width;
                if (xmin < bounds.XMin)
                {
                    left = (bounds.XMin - dataRect.XMin) * scale;
                    xmin = bounds.XMin;
                }

                double width = output.Width - left;
                double xmax  = dataRect.XMax;
                if (xmax > bounds.XMax)
                {
                    width -= (dataRect.XMax - bounds.XMax) * scale;
                    xmax   = bounds.XMax;
                }

                scale = output.Height / dataRect.Height;
                double top  = 0;
                double ymax = dataRect.YMax;
                if (ymax > bounds.YMax)
                {
                    top  = (dataRect.YMax - bounds.YMax) * scale;
                    ymax = bounds.YMax;
                }

                double height = output.Height - top;
                double ymin   = dataRect.YMin;
                if (ymin < bounds.YMin)
                {
                    height -= (bounds.YMin - dataRect.YMin) * scale;
                    ymin    = bounds.YMin;
                }

                if (xmin < bounds.XMin)
                {
                    xmin = bounds.XMin;
                }
                if (xmax > bounds.XMax)
                {
                    xmax = bounds.XMax;
                }
                if (ymin < bounds.YMin)
                {
                    ymin = bounds.YMin;
                }
                if (ymax > bounds.YMax)
                {
                    ymax = bounds.YMax;
                }

                DataRect visibleData = new DataRect(xmin, ymin, xmax, ymax);

                // Capture data to local variable
                double[,] localData;
                double[] localX, localY;
                long     localDataVersion;
                IPalette localPalette;
                double   localMV;
                Range    localDataRange;
                bool     getMaxMin = false;
                lock (locker)
                {
                    localData        = data;
                    localX           = xArr;
                    localY           = yArr;
                    localDataVersion = dataVersion;
                    localPalette     = palette;
                    localMV          = missingValue;
                    localDataRange   = dataRange;
                    if (palette.IsNormalized && dataVersion != dataRangeVersion)
                    {
                        getMaxMin = true;
                    }
                }
                if (getMaxMin)
                {
                    localDataRange = Double.IsNaN(missingValue) ?
                                     HeatmapBuilder.GetMaxMin(data) :
                                     HeatmapBuilder.GetMaxMin(data, missingValue);
                    lock (locker)
                    {
                        if (dataVersion == localDataVersion)
                        {
                            dataRangeVersion = dataVersion;
                            dataRange        = localDataRange;
                        }
                        else
                        {
                            return(null); // New data was passed to Plot method so this render task is obsolete
                        }
                    }
                }
                if (paletteRangeUpdateRequired)
                {
                    Dispatcher.BeginInvoke(new Action <long>(UpdatePaletteRange), localDataVersion);
                }
                return(new RenderResult(HeatmapBuilder.BuildHeatMap(new Rect(0, 0, width, height),
                                                                    visibleData, localX, localY, localData, localMV, localPalette, localDataRange), visibleData, new Point(left, top), width, height));
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Builds heatmap from specified data, grid, missing value, visibleRect and palette.
        /// </summary>
        /// <param name="data">2D array with data to plot</param>
        /// <param name="missingValue">Missing value. Heatmap will have transparent regions at missing value.</param>
        /// <param name="palette">Palette to translate numeric values to colors</param>
        /// <param name="range">Min and max values in <paramref name="data"/> array</param>
        /// <param name="rect">Heatmap rectangle screen coordinates</param>
        /// <param name="screen">Plot rectaneg screen coordinates</param>
        static public int[] BuildHeatMap(Rect screen, DataRect rect, double[] x, double[] y, double[,] data,
                                         double missingValue, IPalette palette, Range range)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (x == null)
            {
                throw new ArgumentNullException("x");
            }
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }
            if (palette == null)
            {
                throw new ArgumentNullException("palette");
            }

            int pixelWidth  = (int)screen.Width;
            int pixelHeight = (int)screen.Height;

            int[]  pixels             = new int[pixelWidth * pixelHeight];
            double doubleMissingValue = missingValue;

            UInt32[] paletteColors = new uint[512];

            if (!palette.IsNormalized)
            {
                range = palette.Range;
            }

            for (int i = 0; i < 512; i++)
            {
                Color c;
                if (palette.IsNormalized)
                {
                    c = palette.GetColor((double)i / 511.0);
                }
                else
                {
                    c = palette.GetColor(range.Min + i * (range.Max - range.Min) / 511.0);
                }

                paletteColors[i] = (((uint)(c.A)) << 24) | (((uint)c.R) << 16) | (((uint)c.G) << 8) | c.B;
            }

            int xdimRank = x.Length;
            int ydimRank = y.Length;

            int xdataRank = data.GetLength(0);
            int ydataRank = data.GetLength(1);

            double factor = (range.Max != range.Min) ? (1.0 / (range.Max - range.Min)) : 0.0;

            if (xdataRank == xdimRank && ydataRank == ydimRank)
            {
                double[,] v = null;
                v           = Filter(pixelWidth, pixelHeight, rect, x, y, data, doubleMissingValue);
                if (palette.IsNormalized)
                {
                    if (Double.IsNaN(doubleMissingValue))
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = v[i, pixelHeight - j - 1];
                                if (!Double.IsNaN(vv))
                                {
                                    double v01 = (vv - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = v[i, pixelHeight - j - 1];
                                if (vv != doubleMissingValue)
                                {
                                    double v01 = (vv - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                }
                else // Palette is absolute
                {
                    if (Double.IsNaN(doubleMissingValue))
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = v[i, pixelHeight - j - 1];
                                if (!Double.IsNaN(vv))
                                {
                                    double v01 = (Math.Max(range.Min, Math.Min(range.Max, vv)) - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = v[i, pixelHeight - j - 1];
                                if (vv != doubleMissingValue)
                                {
                                    double v01 = (Math.Max(range.Min, Math.Min(range.Max, vv)) - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                }
            }
            else if ((xdataRank + 1) == xdimRank && (ydataRank + 1) == ydimRank)
            {
                // Prepare arrays
                int[] xPixelDistrib;
                int[] yPixelDistrib;

                xPixelDistrib = CreatePixelToDataMap(pixelWidth, Math.Max(x[0], rect.XMin), Math.Min(x[x.Length - 1], rect.XMax), x);
                yPixelDistrib = CreatePixelToDataMap(pixelHeight, Math.Max(y[0], rect.YMin), Math.Min(y[y.Length - 1], rect.YMax), y);

                if (palette.IsNormalized)
                {
                    if (Double.IsNaN(doubleMissingValue))
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = data[xPixelDistrib[i], yPixelDistrib[pixelHeight - j - 1]];
                                if (!Double.IsNaN(vv))
                                {
                                    double v01 = (vv - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = data[xPixelDistrib[i], yPixelDistrib[pixelHeight - j - 1]];
                                if (vv != doubleMissingValue)
                                {
                                    double v01 = (vv - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                }
                else // Palette is absolute
                {
                    if (Double.IsNaN(doubleMissingValue))
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = data[xPixelDistrib[i], yPixelDistrib[pixelHeight - j - 1]];
                                if (!Double.IsNaN(vv))
                                {
                                    double v01 = (Math.Max(range.Min, Math.Min(range.Max, vv)) - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0, k = 0; j < pixelHeight; j++)
                        {
                            for (int i = 0; i < pixelWidth; i++, k++)
                            {
                                double vv = data[xPixelDistrib[i], yPixelDistrib[pixelHeight - j - 1]];
                                if (vv != doubleMissingValue)
                                {
                                    double v01 = (Math.Max(range.Min, Math.Min(range.Max, vv)) - range.Min) * factor;
                                    pixels[k] = (int)paletteColors[((uint)(511 * v01)) & 0x1FF];
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                throw new ArgumentException("Size of x,y and data arrays does not match conditions");
            }

            return(pixels);
        }
        /// <summary>Performs array resize and subset with linear interpolation</summary>
        /// <param name="width">Result width</param>
        /// <param name="height">Result height</param>
        /// <param name="rect">Range of coordinates for entire data</param>
        /// <param name="x">Coordinates of x points (length of array must be <paramref name="width"/></param>
        /// <param name="y">Coordinates of y points (length of array must be <paramref name="height"/></param>
        /// <param name="data">Source data array</param>
        /// <param name="missingValue">Missing value or NaN if no missing value</param>
        /// <returns>Resulting array with size <paramref name="width"/> * <paramref name="height"/></returns>
        public static double[,] Filter(int width, int height, DataRect rect,
                                       double[] x, double[] y, double[,] data, double missingValue)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (x == null)
            {
                throw new ArgumentNullException("x");
            }
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            // Check preconditions
            if (x.Length != data.GetLength(0))
            {
                throw new ArgumentException("Size of x and data arrays does not match");
            }
            if (y.Length != data.GetLength(1))
            {
                throw new ArgumentException("Size of y and data arrays does not match");
            }

            // Prepare filters
            int[]    hp, vp, hi, vi;
            double[] ha, va, hw, vw;
            PrepareFilterTables(width, rect.XMin, rect.XMax, x, out hp, out hi, out ha, out hw);
            PrepareFilterTables(height, rect.YMin, rect.YMax, y, out vp, out vi, out va, out vw);

            // Prepare arrays
            double[,] r = new double[width, height];
            bool   hasMissingValue = !Double.IsNaN(missingValue);
            double offset          = 0;

            if (hasMissingValue && missingValue == 0)
            {
                offset = -1;
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        r[i, j] = offset;
                    }
                }
            }

            // Do filtering
            int hpLen = hp.Length;
            int vpLen = vp.Length;

            for (int i = 0; i < hpLen; i++)
            {
                int px = hp[i];
                int i0 = hi[i];

                for (int j = 0; j < vpLen; j++)
                {
                    int py = vp[j];
                    if (hasMissingValue && r[px, py] == missingValue)
                    {
                        continue;
                    }
                    int j0 = vi[j];
                    if (hasMissingValue &&
                        (data[i0, j0] == missingValue ||
                         data[i0 + 1, j0] == missingValue ||
                         data[i0, j0 + 1] == missingValue ||
                         data[i0 + 1, j0 + 1] == missingValue))
                    {
                        r[px, py] = missingValue;
                    }
                    else
                    {
                        double v0 = ha[i] * data[i0, j0] + (1 - ha[i]) * data[i0 + 1, j0];
                        double v1 = ha[i] * data[i0, j0 + 1] + (1 - ha[i]) * data[i0 + 1, j0 + 1];
                        double v  = va[j] * v0 + (1 - va[j]) * v1;
                        r[px, py] += v * hw[i] * vw[j];
                    }
                }
            }
            // Offset data if needed
            if (offset != 0)
            {
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (r[i, j] != missingValue)
                        {
                            r[i, j] -= offset;
                        }
                    }
                }
            }

            return(r);
        }
Exemple #17
0
        /// <summary>
        /// Measures the size in layout required for child elements and determines a size for the Figure.
        /// </summary>
        /// <param name="availableSize">The available size that this element can give to child elements. Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param>
        /// <returns>The size that this element determines it needs during layout, based on its calculations of child element sizes.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            // Assuming we are master panel
            var topElts    = Children.Cast <UIElement>().Where(elt => GetPlacement(elt) == Placement.Top);
            var bottomElts = Children.Cast <UIElement>().Where(elt => GetPlacement(elt) == Placement.Bottom);
            var centerElts = Children.Cast <UIElement>().Where(elt => GetPlacement(elt) == Placement.Center);
            var rightElts  = Children.Cast <UIElement>().Where(elt => GetPlacement(elt) == Placement.Right);
            var leftElts   = Children.Cast <UIElement>().Where(elt => GetPlacement(elt) == Placement.Left);

            DataRect desiredRect;

            if (IsAutoFitEnabled)
            {
                desiredRect = AggregateBounds();
                if (desiredRect.IsEmpty)
                {
                    desiredRect = new DataRect(0, 0, 1, 1);
                }
                SetPlotRect(desiredRect, true);
            }
            else // resize
            {
                desiredRect = PlotRect;
            }

            //First Iteration: Measuring top and bottom slots,
            //then meassuring left and right with top and bottom output values

            // Create transform for first iteration
            if (double.IsNaN(availableSize.Width) || double.IsNaN(availableSize.Height) ||
                double.IsInfinity(availableSize.Width) || double.IsInfinity(availableSize.Height))
            {
                availableSize = new Size(100, 100);
            }

            Fit(desiredRect, availableSize);

            // Measure top and bottom slots
            double topBottomWidth  = 0;
            double topBottomHeight = 0;

            topHeight    = 0;
            bottomHeight = 0;

            foreach (var elt in topElts)
            {
                elt.Measure(availableSize);
                var ds = elt.DesiredSize;
                topBottomWidth = Math.Max(topBottomWidth, ds.Width);
                topHeight     += ds.Height;
            }
            topBottomHeight += topHeight;

            foreach (var elt in bottomElts)
            {
                elt.Measure(availableSize);
                var ds = elt.DesiredSize;
                topBottomWidth = Math.Max(topBottomWidth, ds.Width);
                bottomHeight  += ds.Height;
            }
            topBottomHeight += bottomHeight;

            // Measure left and right slots
            double leftRightWidth  = 0;
            double leftRightHeight = 0;

            leftWidth  = 0;
            rightWidth = 0;

            foreach (var elt in leftElts)
            {
                elt.Measure(availableSize);
                var ds = elt.DesiredSize;
                leftRightHeight = Math.Max(leftRightHeight, ds.Height);
                leftWidth      += ds.Width;
            }
            leftRightWidth += leftWidth;

            foreach (var elt in rightElts)
            {
                elt.Measure(availableSize);
                var ds = elt.DesiredSize;
                leftRightHeight = Math.Max(leftRightHeight, ds.Height);
                rightWidth     += ds.Width;
            }
            leftRightWidth += rightWidth;

            //Measure center elements
            Size availCenterSize = new Size(Math.Max(0, availableSize.Width - leftRightWidth), Math.Max(0, availableSize.Height - topBottomHeight));

            Fit(desiredRect, availCenterSize);

            foreach (var elt in centerElts)
            {
                elt.Measure(availCenterSize);
            }

            // Remeasure top and bottom slots
            double topBottomWidth2  = 0;
            double topBottomHeight2 = 0;

            topHeight2    = 0;
            bottomHeight2 = 0;

            foreach (var elt in topElts)
            {
                elt.Measure(new Size(availCenterSize.Width, elt.DesiredSize.Height));
                var ds = elt.DesiredSize;
                topBottomWidth2 = Math.Max(topBottomWidth2, ds.Width);
                topHeight2     += ds.Height;
            }
            topBottomHeight2 += topHeight2;

            foreach (var elt in bottomElts)
            {
                elt.Measure(new Size(availCenterSize.Width, elt.DesiredSize.Height));
                var ds = elt.DesiredSize;
                topBottomWidth2 = Math.Max(topBottomWidth2, ds.Width);
                bottomHeight2  += ds.Height;
            }
            topBottomHeight2 += bottomHeight2;


            //Scaling elements of their new meassured height it not equal to first
            if (bottomHeight2 > bottomHeight)
            {
                ScaleTransform transform = new ScaleTransform {
                    ScaleY = bottomHeight / bottomHeight2
                };
                foreach (var elt in bottomElts)
                {
                    elt.RenderTransform = transform;
                }
            }

            if (topHeight2 > topHeight)
            {
                ScaleTransform transform = new ScaleTransform {
                    ScaleY = topHeight / topHeight2
                };
                foreach (var elt in topElts)
                {
                    elt.RenderTransform = transform;
                }
            }

            // ReMeasure left and right slots
            double leftRightWidth2  = 0;
            double leftRightHeight2 = 0;

            leftWidth2  = 0;
            rightWidth2 = 0;

            foreach (var elt in leftElts)
            {
                elt.Measure(new Size(elt.DesiredSize.Width, availCenterSize.Height));
                var ds = elt.DesiredSize;
                leftRightHeight2 = Math.Max(leftRightHeight2, ds.Height);
                leftWidth2      += ds.Width;
            }
            leftRightWidth2 += leftWidth2;

            foreach (var elt in rightElts)
            {
                elt.Measure(new Size(elt.DesiredSize.Width, availCenterSize.Height));
                var ds = elt.DesiredSize;
                leftRightHeight2 = Math.Max(leftRightHeight2, ds.Height);
                rightWidth2     += ds.Width;
            }
            leftRightWidth2 += rightWidth2;

            //Scaling elements of their new meassured height it not equal to first
            if (leftWidth2 > leftWidth)
            {
                ScaleTransform transform = new ScaleTransform {
                    ScaleX = leftWidth / leftWidth2
                };
                foreach (var elt in leftElts)
                {
                    elt.RenderTransform = transform;
                }
            }

            if (rightWidth2 > rightWidth)
            {
                ScaleTransform transform = new ScaleTransform {
                    ScaleX = rightWidth / rightWidth2
                };
                foreach (var elt in rightElts)
                {
                    elt.RenderTransform = transform;
                }
            }

            centerSize = availCenterSize;
            return(new Size(availCenterSize.Width + leftRightWidth, availCenterSize.Height + topBottomHeight));
        }