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 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); }