예제 #1
0
 private Color GetDotColor(ISOMInput item)
 {
     if (_getDotColor == null)
     {
         return(UtilityWPF.GetRandomColor(96, 192));
     }
     else
     {
         return(_getDotColor(item));
     }
 }
 public DrawTileArgs(ISOMInput tile, int tileWidth, int tileHeight, byte[] bitmapPixelBytes, int imageX, int imageY, int stride, int pixelWidth)
 {
     this.Tile = tile;
     this.TileWidth = tileWidth;
     this.TileHeight = tileHeight;
     this.BitmapPixelBytes = bitmapPixelBytes;
     this.ImageX = imageX;
     this.ImageY = imageY;
     this.Stride = stride;
     this.PixelWidth = pixelWidth;
 }
예제 #3
0
 public DrawTileArgs(ISOMInput tile, int tileWidth, int tileHeight, byte[] bitmapPixelBytes, int imageX, int imageY, int stride, int pixelWidth)
 {
     this.Tile             = tile;
     this.TileWidth        = tileWidth;
     this.TileHeight       = tileHeight;
     this.BitmapPixelBytes = bitmapPixelBytes;
     this.ImageX           = imageX;
     this.ImageY           = imageY;
     this.Stride           = stride;
     this.PixelWidth       = pixelWidth;
 }
예제 #4
0
        private static bool IsSame(ISOMInput input1, ISOMInput input2)
        {
            if (input1 == null && input2 == null)
            {
                return(true);
            }
            else if (input1 == null || input2 == null)
            {
                return(false);
            }

            return(IsSame(input1.Weights, input2.Weights));
        }
예제 #5
0
        private static bool IsTooClose(ISOMInput item, IEnumerable <ISOMInput> others, double dupeDistSquared)
        {
            foreach (ISOMInput other in others)
            {
                double distSqr = (item.Weights - other.Weights).LengthSquared;

                if (distSqr < dupeDistSquared)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #6
0
        public static Tuple <SOMNode, int> GetClosest(SOMNode[] nodes, ISOMInput input)
        {
            int     closestIndex = -1;
            double  closest      = double.MaxValue;
            SOMNode retVal       = null;

            for (int cntr = 0; cntr < nodes.Length; cntr++)
            {
                double distSquared = (nodes[cntr].Weights - input.Weights).LengthSquared;

                if (distSquared < closest)
                {
                    closestIndex = cntr;
                    closest      = distSquared;
                    retVal       = nodes[cntr];
                }
            }

            return(Tuple.Create(retVal, closestIndex));
        }
        private static Canvas DrawVoronoi_Tiled(VoronoiResult2D voronoi, SOMNode[] nodes, ISOMInput[][] images, int imageWidth, int imageHeight, int tileWidth, int tileHeight, Action<DrawTileArgs> drawTile, BlobEvents events)
        {
            #region transform

            var aabb = Math2D.GetAABB(voronoi.EdgePoints);

            TransformGroup transform = new TransformGroup();
            transform.Children.Add(new TranslateTransform(-aabb.Item1.X, -aabb.Item1.Y));
            transform.Children.Add(new ScaleTransform(imageWidth / (aabb.Item2.X - aabb.Item1.X), imageHeight / (aabb.Item2.Y - aabb.Item1.Y)));

            #endregion

            Canvas retVal = new Canvas();

            for (int cntr = 0; cntr < voronoi.ControlPoints.Length; cntr++)
            {
                #region polygon

                Polygon polygon = new Polygon();

                if (voronoi.EdgesByControlPoint[cntr].Length < 3)
                {
                    throw new ApplicationException("Expected at least three edge points");
                }

                Edge2D[] edges = voronoi.EdgesByControlPoint[cntr].Select(o => voronoi.Edges[o]).ToArray();
                Point[] edgePoints = Edge2D.GetPolygon(edges, 1d);

                edgePoints = edgePoints.
                    Select(o => transform.Transform(o)).
                    ToArray();

                foreach (Point point in edgePoints)
                {
                    polygon.Points.Add(point);
                }

                polygon.Fill = GetTiledSamples(edgePoints, images[cntr], nodes[cntr], tileWidth, tileHeight, drawTile);
                polygon.Stroke = new SolidColorBrush(UtilityWPF.GetRandomColor(64, 192));
                polygon.StrokeThickness = 2;

                polygon.Tag = Tuple.Create(nodes[cntr], images[cntr]);

                if (events != null)
                {
                    if (events.MouseMove != null && events.MouseLeave != null)
                    {
                        polygon.MouseMove += Polygon2D_MouseMove;
                        polygon.MouseLeave += Polygon2D_MouseLeave;
                    }

                    if (events.Click != null)
                    {
                        polygon.MouseUp += Polygon_MouseUp;
                    }
                }

                retVal.Children.Add(polygon);

                #endregion
            }

            return retVal;
        }
        private static Canvas DrawVoronoi_Blobs(VoronoiResult2D voronoi, Color[] colors, SOMNode[] nodes, ISOMInput[][] inputsByNode, int imageWidth, int imageHeight, BlobEvents events)
        {
            const double MARGINPERCENT = 1.05;

            // Analyze size ratios
            double[] areas = AnalyzeVoronoiCellSizes(voronoi, inputsByNode);

            #region transform

            var aabb = Math2D.GetAABB(voronoi.EdgePoints);
            aabb = Tuple.Create((aabb.Item1.ToVector() * MARGINPERCENT).ToPoint(), (aabb.Item2.ToVector() * MARGINPERCENT).ToPoint());

            TransformGroup transform = new TransformGroup();
            transform.Children.Add(new TranslateTransform(-aabb.Item1.X, -aabb.Item1.Y));
            transform.Children.Add(new ScaleTransform(imageWidth / (aabb.Item2.X - aabb.Item1.X), imageHeight / (aabb.Item2.Y - aabb.Item1.Y)));

            #endregion

            Canvas retVal = new Canvas();
            retVal.Effect = new DropShadowEffect()
            {
                Color = Colors.Gray,
                Opacity = .2,
                BlurRadius = 5,
                Direction = 0,
                ShadowDepth = 0,
            };

            for (int cntr = 0; cntr < voronoi.ControlPoints.Length; cntr++)
            {
                #region polygon

                Polygon polygon = new Polygon();

                if (voronoi.EdgesByControlPoint[cntr].Length < 3)
                {
                    throw new ApplicationException("Expected at least three edge points");
                }

                Edge2D[] edges = voronoi.EdgesByControlPoint[cntr].Select(o => voronoi.Edges[o]).ToArray();
                Point[] edgePoints = Edge2D.GetPolygon(edges, 1d);

                // Resize to match the desired area
                edgePoints = ResizeConvexPolygon(edgePoints, areas[cntr]);

                // Convert into a smooth blob
                BezierSegment3D[] bezier = BezierUtil.GetBezierSegments(edgePoints.Select(o => o.ToPoint3D()).ToArray(), .25, true);
                edgePoints = BezierUtil.GetPath(75, bezier).
                    Select(o => o.ToPoint2D()).
                    ToArray();

                // Transform to canvas coords
                edgePoints = edgePoints.
                    Select(o => transform.Transform(o)).
                    ToArray();

                foreach (Point point in edgePoints)
                {
                    polygon.Points.Add(point);
                }

                polygon.Fill = new SolidColorBrush(colors[cntr]);
                polygon.Stroke = null; // new SolidColorBrush(UtilityWPF.OppositeColor(colors[cntr], false));
                polygon.StrokeThickness = 1;

                polygon.Tag = Tuple.Create(events, nodes[cntr], inputsByNode[cntr]);

                if (events != null)
                {
                    if (events.MouseMove != null && events.MouseLeave != null)
                    {
                        polygon.MouseMove += Polygon2D_MouseMove;
                        polygon.MouseLeave += Polygon2D_MouseLeave;
                    }

                    if (events.Click != null)
                    {
                        polygon.MouseUp += Polygon_MouseUp;
                    }
                }

                retVal.Children.Add(polygon);

                #endregion
            }

            return retVal;
        }
 /// <summary>
 /// This divides the node's weights into thirds, and maps to RGB
 /// </summary>
 public static Color GetNodeColor(ISOMInput node)
 {
     var raw = GetNodeColor_RGB(node.Weights);
     return GetNodeColor_Finish(raw);
 }
예제 #10
0
        /// <summary>
        /// This divides the node's weights into thirds, and maps to RGB
        /// </summary>
        public static Color GetNodeColor(ISOMInput node)
        {
            var raw = GetNodeColor_RGB(node.Weights);

            return(GetNodeColor_Finish(raw));
        }
        private static Brush GetTiledSamples_ONE(Point[] edgePoints, ISOMInput[] samples)
        {
            var aabb = Math2D.GetAABB(edgePoints);

            var colors = Enumerable.Range(0, 256).
                Select(o => UtilityWPF.GetRandomColor(64, 192)).
                ToArray();

            //BitmapSource bitmap = UtilityWPF.GetBitmap_Aliased(colors, 16, 16, 300, 300);
            BitmapSource bitmap = UtilityWPF.GetBitmap_Aliased(colors, 16, 16, (aabb.Item2.X - aabb.Item1.X).ToInt_Round(), (aabb.Item2.Y - aabb.Item1.Y).ToInt_Round());

            return new ImageBrush(bitmap)
            {
                Stretch = Stretch.None,
            };
        }
        private void BuildOverlay2D(SOMNode node, ISOMInput[] inputs, bool showCount = false, bool showNodeHash = false)
        {
            const double SMALLFONT1 = 17;
            const double LARGEFONT1 = 21;
            const double SMALLFONT2 = 15;
            const double LARGEFONT2 = 18;
            const double SMALLFONT3 = 12;
            const double LARGEFONT3 = 14;

            const double SMALLLINE1 = .8;
            const double LARGELINE1 = 1;
            const double SMALLLINE2 = .5;
            const double LARGELINE2 = .85;
            const double SMALLLINE3 = .3;
            const double LARGELINE3 = .7;

            Canvas canvas = new Canvas();
            List<Rect> rectangles = new List<Rect>();

            #region cursor rectangle

            var cursorRect = SelfOrganizingMapsWPF.GetMouseCursorRect();
            rectangles.Add(cursorRect.Item1);

            // This is just for debugging
            //Rectangle cursorVisual = new Rectangle()
            //{
            //    Width = cursorRect.Item1.Width,
            //    Height = cursorRect.Item1.Height,
            //    Fill = new SolidColorBrush(UtilityWPF.GetRandomColor(64, 192, 255)),
            //};

            //Canvas.SetLeft(cursorVisual, cursorRect.Item1.Left);
            //Canvas.SetTop(cursorVisual, cursorRect.Item1.Top);

            //canvas.Children.Add(cursorVisual);

            #endregion

            #region count text

            if (showCount && _result != null && _result.InputsByNode != null)       // it's possible that they are changing things while old graphics are still showing
            {
                StackPanel textPanel = new StackPanel()
                {
                    Orientation = Orientation.Horizontal,
                };

                // "rows "
                OutlinedTextBlock text = SelfOrganizingMapsWPF.GetOutlineText("rows ", SMALLFONT1, SMALLLINE1);
                text.Margin = new Thickness(0, 0, 4, 0);
                textPanel.Children.Add(text);

                // percent
                double percent = -1;
                if (_result.InputsByNode.Length == 0)
                {
                    if (inputs.Length == 0)
                    {
                        percent = 0;
                    }
                    else
                    {
                        percent = -1;
                    }
                }
                else
                {
                    percent = inputs.Length.ToDouble() / _result.InputsByNode.SelectMany(o => o).Count().ToDouble();
                    percent *= 100d;
                }
                text = SelfOrganizingMapsWPF.GetOutlineText(percent.ToStringSignificantDigits(2) + "%", LARGEFONT1, LARGELINE1);
                textPanel.Children.Add(text);

                // Place on canvas
                textPanel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));       // aparently, the infinity is important to get an accurate desired size
                Size textSize = textPanel.DesiredSize;

                Rect textRect = SelfOrganizingMapsWPF.GetFreeSpot(textSize, new Point(0, 0), new Vector(0, -1), rectangles);
                rectangles.Add(textRect);

                Canvas.SetLeft(textPanel, textRect.Left);
                Canvas.SetTop(textPanel, textRect.Top);

                canvas.Children.Add(textPanel);
            }

            #endregion

            double[] nodeCenter = inputs.Length == 0 ? node.Weights : MathND.GetCenter(inputs.Select(o => o.Weights));

            #region node hash

            if (showNodeHash)
            {
                var nodeCtrl = GetVectorVisual(node.Weights);

                // Place on canvas
                Rect nodeRect = SelfOrganizingMapsWPF.GetFreeSpot(new Size(nodeCtrl.Item2.X, nodeCtrl.Item2.Y), new Point(0, 0), new Vector(0, -1), rectangles);
                rectangles.Add(nodeRect);

                Canvas.SetLeft(nodeCtrl.Item1, nodeRect.Left);
                Canvas.SetTop(nodeCtrl.Item1, nodeRect.Top);

                canvas.Children.Add(nodeCtrl.Item1);
            }

            #endregion

            //TODO: For the first attempt, put all row descriptions under
            #region rows

            if (_queryResults != null && _queryResults.Results != null)
            {
                var rowsCtrl = GetRowsVisual(_queryResults.ColumnNames, inputs, _detailsHeaderStyle, _detailsBodyStyle);

                // Place on canvas
                Rect rowsRect = SelfOrganizingMapsWPF.GetFreeSpot(new Size(rowsCtrl.Item2.X, rowsCtrl.Item2.Y), new Point(0, 0), new Vector(0, 1), rectangles);
                rectangles.Add(rowsRect);

                Canvas.SetLeft(rowsCtrl.Item1, rowsRect.Left);
                Canvas.SetTop(rowsCtrl.Item1, rowsRect.Top);

                canvas.Children.Add(rowsCtrl.Item1);
            }

            #endregion

            Rect canvasAABB = Math2D.GetAABB(rectangles);

            //NOTE: All the items are placed around zero zero, but that may not be half width and height (items may not be centered)
            canvas.RenderTransform = new TranslateTransform(-canvasAABB.Left, -canvasAABB.Top);

            panelOverlay.Children.Clear();
            panelOverlay.Children.Add(canvas);

            _overlayPolyStats = new OverlayPolygonStats(node, inputs, canvasAABB, cursorRect.Item2, canvas);
        }
        private void Polygon_Click(Polygon sender, SOMNode node, ISOMInput[] images, MouseEventArgs e)
        {
            try
            {
                Color nodeColor = UtilityWPF.ExtractColor(sender.Fill);

                RadialGradientBrush brush = new RadialGradientBrush();
                brush.GradientStops.Add(new GradientStop(UtilityWPF.AlphaBlend(Colors.White, nodeColor, .8), 0));
                brush.GradientStops.Add(new GradientStop(UtilityWPF.AlphaBlend(Colors.White, nodeColor, .58), 1.9));

                HighDimensionVisualizer visualizer = new HighDimensionVisualizer(GetPreviewImage, SelfOrganizingMapsWPF.GetNodeColor, chkVisualizerStaticDots.IsChecked.Value, chkVisualizer3D.IsChecked.Value);
                visualizer.AddStaticItems(HighDimensionVisualizer.GetSOMNodeStaticPositions(node, _nodes, HighDimensionVisualizer.RADIUS));
                visualizer.AddItems(images);

                Window window = new Window()
                {
                    Width = 400,
                    Height = 400,
                    Title = this.Title + " " + images.Length.ToString(),
                    Background = brush,
                    ResizeMode = ResizeMode.CanResizeWithGrip,
                    Content = visualizer,
                    Owner = this,       // keep it on top of this window
                };

                window.Show();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        /// <summary>
        /// This is used by child HighDimensionVisualizer windows
        /// </summary>
        private Tuple<UIElement, VectorInt> GetPreviewImage(ISOMInput input)
        {
            bool showHash = chkVisualizerShowHash.IsChecked.Value;

            ImageInput nodeImage = input as ImageInput;
            if (nodeImage == null)
            {
                // This is probably a node, instead of an input image (the nodes are sent as static control points)
                nodeImage = new ImageInput(null, input.Weights, input.Weights);
                showHash = true;
            }

            return GetPreviewImage(nodeImage, showHash, 80, false, -1);
        }
        private void BuildOverlay2D(SOMNode node, ISOMInput[] images, bool showCount, bool showNodeHash, bool showImageHash, bool showSpread, bool showPerImageDistance)
        {
            const int IMAGESIZE = 80;
            const int NODEHASHSIZE = 100;

            const double SMALLFONT1 = 17;
            const double LARGEFONT1 = 21;
            const double SMALLFONT2 = 15;
            const double LARGEFONT2 = 18;
            const double SMALLFONT3 = 12;
            const double LARGEFONT3 = 14;

            const double SMALLLINE1 = .8;
            const double LARGELINE1 = 1;
            const double SMALLLINE2 = .5;
            const double LARGELINE2 = .85;
            const double SMALLLINE3 = .3;
            const double LARGELINE3 = .7;

            Canvas canvas = new Canvas();
            List<Rect> rectangles = new List<Rect>();

            #region cursor rectangle

            var cursorRect = SelfOrganizingMapsWPF.GetMouseCursorRect(0);
            rectangles.Add(cursorRect.Item1);

            // This is just for debugging
            //Rectangle cursorVisual = new Rectangle()
            //{
            //    Width = cursorRect.Item1.Width,
            //    Height = cursorRect.Item1.Height,
            //    Fill = new SolidColorBrush(UtilityWPF.GetRandomColor(64, 192, 255)),
            //};

            //Canvas.SetLeft(cursorVisual, cursorRect.Item1.Left);
            //Canvas.SetTop(cursorVisual, cursorRect.Item1.Top);

            //canvas.Children.Add(cursorVisual);

            #endregion

            #region count text

            if (showCount)
            {
                StackPanel textPanel = new StackPanel()
                {
                    Orientation = Orientation.Horizontal,
                };

                // "images "
                OutlinedTextBlock text = SelfOrganizingMapsWPF.GetOutlineText("images ", SMALLFONT1, SMALLLINE1);
                text.Margin = new Thickness(0, 0, 4, 0);
                textPanel.Children.Add(text);

                // count
                text = SelfOrganizingMapsWPF.GetOutlineText(images.Length.ToString("N0"), LARGEFONT1, LARGELINE1);
                textPanel.Children.Add(text);

                // Place on canvas
                textPanel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));       // aparently, the infinity is important to get an accurate desired size
                Size textSize = textPanel.DesiredSize;

                Rect textRect = SelfOrganizingMapsWPF.GetFreeSpot(textSize, new Point(0, 0), new Vector(0, 1), rectangles);
                rectangles.Add(textRect);

                Canvas.SetLeft(textPanel, textRect.Left);
                Canvas.SetTop(textPanel, textRect.Top);

                canvas.Children.Add(textPanel);
            }

            #endregion
            #region spread

            var nodeImages = images.Select(o => o.Weights);
            var allImages = _imagesByNode.SelectMany(o => o).Select(o => o.Weights);

            double nodeSpread = images.Length == 0 ? 0d : SelfOrganizingMaps.GetTotalSpread(nodeImages);
            double totalSpread = SelfOrganizingMaps.GetTotalSpread(allImages);

            if (showSpread && images.Length > 0)
            {
                double nodeStandDev = MathND.GetStandardDeviation(nodeImages);
                double totalStandDev = MathND.GetStandardDeviation(allImages);

                double percentSpread = nodeSpread / totalSpread;
                double pecentStandDev = nodeStandDev / totalSpread;

                Grid spreadPanel = new Grid()
                {
                    Margin = new Thickness(2),
                };
                spreadPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
                spreadPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(4) });
                spreadPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });

                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(2) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(2) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(2) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(2) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(2) });
                spreadPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });

                AddTextRow(spreadPanel, 0, "node stand dev", (pecentStandDev * 100).ToStringSignificantDigits(2) + "%", SMALLFONT2, LARGEFONT2, SMALLLINE2, LARGELINE2, true);
                AddTextRow(spreadPanel, 2, "node spread", (percentSpread * 100).ToStringSignificantDigits(2) + "%", SMALLFONT2, LARGEFONT2, SMALLLINE2, LARGELINE2, false);

                AddTextRow(spreadPanel, 4, "node stand dev", nodeStandDev.ToStringSignificantDigits(2), SMALLFONT3, LARGEFONT3, SMALLLINE3, LARGELINE3, true);
                AddTextRow(spreadPanel, 6, "node spread", nodeSpread.ToStringSignificantDigits(2), SMALLFONT3, LARGEFONT3, SMALLLINE3, LARGELINE3, false);

                AddTextRow(spreadPanel, 8, "total stand dev", totalStandDev.ToStringSignificantDigits(2), SMALLFONT3, LARGEFONT3, SMALLLINE3, LARGELINE3, true);
                AddTextRow(spreadPanel, 10, "total spread", totalSpread.ToStringSignificantDigits(2), SMALLFONT3, LARGEFONT3, SMALLLINE3, LARGELINE3, false);

                // Place on canvas
                spreadPanel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));       // aparently, the infinity is important to get an accurate desired size
                Size spreadSize = spreadPanel.DesiredSize;

                Rect spreadRect = SelfOrganizingMapsWPF.GetFreeSpot(spreadSize, new Point(0, 0), new Vector(0, 1), rectangles);
                rectangles.Add(spreadRect);

                Canvas.SetLeft(spreadPanel, spreadRect.Left);
                Canvas.SetTop(spreadPanel, spreadRect.Top);

                canvas.Children.Add(spreadPanel);
            }

            #endregion

            double[] nodeCenter = images.Length == 0 ? node.Weights : MathND.GetCenter(nodeImages);

            #region node hash

            if (showNodeHash)
            {
                ImageInput nodeImage = new ImageInput(null, node.Weights, node.Weights);

                double nodeDist = MathND.GetDistance(nodeImage.Weights, nodeCenter);
                double nodeDistPercent = nodeSpread.IsNearZero() ? 1d : (nodeDist / nodeSpread);     // if zero or one node, then spread will be zero

                Tuple<UIElement, VectorInt> nodeCtrl = GetPreviewImage(nodeImage, true, NODEHASHSIZE, showPerImageDistance, nodeDistPercent);

                // Place on canvas
                Rect nodeRect = SelfOrganizingMapsWPF.GetFreeSpot(new Size(nodeCtrl.Item2.X, nodeCtrl.Item2.Y), new Point(0, 0), new Vector(0, -1), rectangles);
                rectangles.Add(nodeRect);

                Canvas.SetLeft(nodeCtrl.Item1, nodeRect.Left);
                Canvas.SetTop(nodeCtrl.Item1, nodeRect.Top);

                canvas.Children.Add(nodeCtrl.Item1);
            }

            #endregion

            #region images

            foreach (ImageInput image in images)
            {
                double imageDistPercent;
                if (images.Length == 1)
                {
                    imageDistPercent = 1;
                }
                else
                {
                    imageDistPercent = MathND.GetDistance(image.Weights, nodeCenter) / nodeSpread;
                }

                // Create the image (and any other graphics for that image)
                Tuple<UIElement, VectorInt> imageCtrl = GetPreviewImage(image, showImageHash, IMAGESIZE, showPerImageDistance, imageDistPercent);

                // Find a spot for it
                var imageRect = Enumerable.Range(0, 10).
                    Select(o =>
                    {
                        Vector direction = Math3D.GetRandomVector_Circular_Shell(1).ToVector2D();

                        Rect imageRect2 = SelfOrganizingMapsWPF.GetFreeSpot(new Size(imageCtrl.Item2.X, imageCtrl.Item2.Y), new Point(0, 0), direction, rectangles);

                        return new { Rect = imageRect2, Distance = new Vector(imageRect2.CenterX(), imageRect2.CenterY()).LengthSquared };
                    }).
                    OrderBy(o => o.Distance).
                    First().
                    Rect;

                Canvas.SetLeft(imageCtrl.Item1, imageRect.Left);
                Canvas.SetTop(imageCtrl.Item1, imageRect.Top);

                // Add it
                rectangles.Add(imageRect);
                canvas.Children.Add(imageCtrl.Item1);
            }

            #endregion

            Rect canvasAABB = Math2D.GetAABB(rectangles);

            //NOTE: All the items are placed around zero zero, but that may not be half width and height (items may not be centered)
            canvas.RenderTransform = new TranslateTransform(-canvasAABB.Left, -canvasAABB.Top);

            panelOverlay.Children.Clear();
            panelOverlay.Children.Add(canvas);

            _overlayPolyStats = new OverlayPolygonStats(node, images, canvasAABB, cursorRect.Item2, canvas);
        }
        private static double[] AnalyzeVoronoiCellSizes(VoronoiResult2D voronoi, ISOMInput[][] imagesByNode)
        {
            // Calculate area, density of each node
            var sizes = Enumerable.Range(0, voronoi.ControlPoints.Length).
                Select(o =>
                {
                    double area = Math2D.GetAreaPolygon(voronoi.GetPolygon(o, 1));        // there are no rays
                    double imageCount = imagesByNode[o].Length.ToDouble();

                    return new
                    {
                        ImagesCount = imageCount,
                        Area = area,
                        Density = imageCount / area,
                    };
                }).
                ToArray();

            // Don't let any node have an area smaller than this
            double minArea = sizes.Min(o => o.Area) * .2;

            // Find the node with the largest density.  This is the density to use when drawing all cells
            var largestDensity = sizes.
                OrderByDescending(o => o.Density).
                First();

            return sizes.Select(o =>
            {
                // Figure out how much area it would take using the highest density
                double area = o.ImagesCount / largestDensity.Density;
                if (area < minArea)
                {
                    area = minArea;
                }

                return area;
            }).
            ToArray();
        }
        private static Tuple<UIElement, VectorInt> GetRowsVisual(string[] columnNames, ISOMInput[] inputs, Style headerStyle, Style bodyStyle)
        {
            Grid grid = new Grid();

            #region Header

            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });

            // Header
            for (int cntr = 0; cntr < columnNames.Length; cntr++)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });

                TextBlock text = new TextBlock()
                {
                    Text = columnNames[cntr],
                    Style = headerStyle,
                };

                Grid.SetColumn(text, cntr);
                Grid.SetRow(text, grid.RowDefinitions.Count - 1);

                grid.Children.Add(text);
            }

            #endregion

            //TODO: Sort by distance.  Call this with 1D coords
            //SelfOrganizingMaps.ArrangeNodes_LikesAttract()
            foreach (RowInput input in UtilityCore.RandomOrder(inputs, 300))       // Mix it up.  Also getting exceptions if too much is added, and it won't all be shown anyway
            {
                #region Body Row

                grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });

                // Header
                for (int cntr = 0; cntr < columnNames.Length; cntr++)
                {
                    grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });

                    TextBlock text = new TextBlock()
                    {
                        Text = input.Row[cntr],
                        Style = bodyStyle,
                        HorizontalAlignment = HorizontalAlignment.Right,
                    };

                    Grid.SetColumn(text, cntr);
                    Grid.SetRow(text, grid.RowDefinitions.Count - 1);

                    grid.Children.Add(text);
                }

                #endregion
            }

            Border retVal = new Border()
            {
                Child = grid,
                Background = new SolidColorBrush(UtilityWPF.ColorFromHex("D0F7F1DA")),
                BorderBrush = new SolidColorBrush(UtilityWPF.ColorFromHex("B8B4A0")),
                BorderThickness = new Thickness(1),
                CornerRadius = new CornerRadius(3),
                Padding = new Thickness(8),
            };

            retVal.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));       // aparently, the infinity is important to get an accurate desired size
            Size returnSize = retVal.DesiredSize;

            return Tuple.Create((UIElement)retVal, new VectorInt(returnSize.Width.ToInt_Ceiling(), returnSize.Height.ToInt_Ceiling()));
        }
        private static Brush GetTiledSamples(Point[] edgePoints, ISOMInput[] samples, SOMNode node, int tileWidth, int tileHeight, Action<DrawTileArgs> drawTile)
        {
            var dimensions = GetTileImagePositions(samples.Length);

            // The image tiles will be drawn spiraling out from the center.  Order the list so that tiles closest to the node are first (so that
            // they are drawn closer to the center of the spiral)
            ISOMInput[] orderedSamples = samples.
                OrderBy(o => MathND.GetDistanceSquared(o.Weights, node.Weights)).
                ToArray();

            //int tilehalf_left = tileWidth / 2;
            //int tilehalf_top = tileHeight / 2;
            //int tilehalf_right = tileWidth - tilehalf_left;
            //int tilehalf_bot = tileHeight - tilehalf_top;

            int imageWidth = (dimensions.Item2.X - dimensions.Item1.X + 1) * tileWidth;
            int imageHeight = (dimensions.Item2.Y - dimensions.Item1.Y + 1) * tileHeight;

            //int offsetX = (Math.Abs(dimensions.Item1.X) * tileWidth) + tilehalf_left;
            //int offsetY = (Math.Abs(dimensions.Item1.Y) * tileHeight) + tilehalf_top;


            //TODO: Get the AABB of edgePoints.  If the bitmap will be bigger than the aabb, then draw just enough to totally fill the polygon



            //NOTE: Copied from UtilityWPF.GetBitmap

            WriteableBitmap bitmap = new WriteableBitmap(imageWidth, imageHeight, UtilityWPF.DPI, UtilityWPF.DPI, PixelFormats.Pbgra32, null);      // may want Bgra32 if performance is an issue

            int pixelWidth = bitmap.Format.BitsPerPixel / 8;
            int stride = bitmap.PixelWidth * pixelWidth;      // this is the length of one row of pixels

            byte[] pixels = new byte[bitmap.PixelHeight * stride];

            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext ctx = dv.RenderOpen())
            {
                for (int cntr = 0; cntr < orderedSamples.Length; cntr++)
                {
                    int x = (dimensions.Item3[cntr].X - dimensions.Item1.X) * tileWidth;
                    int y = (dimensions.Item3[cntr].Y - dimensions.Item1.Y) * tileWidth;

                    DrawTileArgs args = new DrawTileArgs(orderedSamples[cntr], tileWidth, tileHeight, pixels, x, y, stride, pixelWidth);
                    drawTile(args);
                }




                #region DISCARD

                //int index = 0;
                //for (int y = 0; y < colorsHeight; y++)
                //{
                //    for (int x = 0; x < colorsWidth; x++)
                //    {
                //        int gray = (grayColors[index] * grayValueScale).ToInt_Round();
                //        if (gray < 0) gray = 0;
                //        if (gray > 255) gray = 255;
                //        byte grayByte = Convert.ToByte(gray);
                //        Color color = Color.FromRgb(grayByte, grayByte, grayByte);
                //        ctx.DrawRectangle(new SolidColorBrush(color), null, new Rect(x * scaleX, y * scaleY, scaleX, scaleY));
                //        index++;
                //    }
                //}

                #endregion
            }

            bitmap.WritePixels(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight), pixels, stride, 0);



            return new ImageBrush(bitmap)
            {
                Stretch = Stretch.None,
            };
        }
 public OverlayPolygonStats(SOMNode node, ISOMInput[] images, Rect canvasAABB, Vector cursorOffset, Canvas overlay)
 {
     this.Node = node;
     this.Images = images;
     this.CanvasAABB = canvasAABB;
     this.CursorOffset = cursorOffset;
     this.Overlay = overlay;
 }
 private Color GetDotColor(ISOMInput item)
 {
     if (_getDotColor == null)
     {
         return UtilityWPF.GetRandomColor(96, 192);
     }
     else
     {
         return _getDotColor(item);
     }
 }
        private void Polygon_MouseMove(Polygon poly, SOMNode node, ISOMInput[] inputs, MouseEventArgs e)
        {
            try
            {
                if (_overlayPolyStats == null || _overlayPolyStats.Node.Token != node.Token)
                {
                    BuildOverlay2D(node, inputs, true, true);
                }

                Point mousePos = e.GetPosition(panelDisplay);

                double left = mousePos.X + _overlayPolyStats.CanvasAABB.Left + _overlayPolyStats.CursorOffset.X - 1;
                //double top = mousePos.Y + _overlayPolyStats.CanvasAABB.Top + _overlayPolyStats.CursorOffset.Y - 1;
                //double top = mousePos.Y + _overlayPolyStats.CanvasAABB.Top - _overlayPolyStats.CursorOffset.Y - 1;
                double top = mousePos.Y + _overlayPolyStats.CanvasAABB.Top - 1;     // Y is already centered

                Canvas.SetLeft(_overlayPolyStats.Overlay, left);
                Canvas.SetTop(_overlayPolyStats.Overlay, top);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void Polygon_Click(Polygon poly, SOMNode node, ISOMInput[] inputs, MouseEventArgs e)
        {
            try
            {
                int index = _result.Nodes.IndexOf(node, (o, p) => o.Token == p.Token);

                DBRowsDetail viewer = new DBRowsDetail(_queryResults, _columns, _result, index)
                {
                    Background = poly.Fill,
                };

                viewer.Closed += DBRowsDetail_Closed;
                _childWindows.Add(viewer);

                viewer.Show();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
예제 #23
0
        private static bool IsTooClose(ISOMInput item, IEnumerable<ISOMInput> others, double dupeDistSquared)
        {
            foreach (ISOMInput other in others)
            {
                double distSqr = MathND.GetDistanceSquared(item.Weights, other.Weights);

                if (distSqr < dupeDistSquared)
                {
                    return true;
                }
            }

            return false;
        }