示例#1
0
        /// <summary>
        /// This creates solid colored blobs with areas proportional to the number of items contained.  When the user
        /// mouses over a blob, the caller can show examples of the items as tooltips
        /// </summary>
        public static void ShowResults2D_Blobs(Border border, SOMResult result, Func <SOMNode, Color> getNodeColor, BlobEvents events = null)
        {
            #region validate
#if DEBUG
            if (!result.Nodes.All(o => o.Position.Size == 2))
            {
                throw new ArgumentException("Node positions need to be 2D");
            }
#endif
            #endregion

            Point[] points = result.Nodes.
                             Select(o => new Point(o.Position[0], o.Position[1])).
                             ToArray();

            VoronoiResult2D voronoi = Math2D.GetVoronoi(points, true);
            voronoi = Math2D.CapVoronoiCircle(voronoi);

            Color[] colors = result.Nodes.
                             Select(o => getNodeColor(o)).
                             ToArray();

            //ISOMInput[][] inputsByNode = UtilityCore.ConvertJaggedArray<ISOMInput>(result.InputsByNode);

            Vector size   = new Vector(border.ActualWidth - border.Padding.Left - border.Padding.Right, border.ActualHeight - border.Padding.Top - border.Padding.Bottom);
            Canvas canvas = DrawVoronoi_Blobs(voronoi, colors, result.Nodes, result.InputsByNode, size.X.ToInt_Floor(), size.Y.ToInt_Floor(), events);

            border.Child = canvas;
        }
示例#2
0
        private static Point[][] GetPolygons(VoronoiResult2D voronoi, Vector offset)
        {
            Point[][] retVal = new Point[voronoi.ControlPoints.Length][];

            for (int cntr = 0; cntr < voronoi.ControlPoints.Length; cntr++)
            {
                retVal[cntr] = voronoi.GetPolygon(cntr, 1). // don't need to worry about ray length, they are all segments
                               Select(o => o + offset).     // shifting the points by offset
                               ToArray();
            }

            return(retVal);
        }
示例#3
0
        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());
        }
示例#4
0
        /// <summary>
        /// This divides the border up into a voronoi, then each node is tiled with examples
        /// </summary>
        public static void ShowResults2D_Tiled(Border border, SOMResult result, int tileWidth, int tileHeight, Action <DrawTileArgs> drawTile, BlobEvents events = null)
        {
            //TODO: Take a func that will render the input onto a writable bitmap, or something dynamic but efficient?
            // or take these in?
            //int tileWidth, int tileHeight



            Point[] points = result.Nodes.
                             Select(o => new Point(o.Position[0], o.Position[1])).
                             ToArray();

            Vector size = new Vector(border.ActualWidth - border.Padding.Left - border.Padding.Right, border.ActualHeight - border.Padding.Top - border.Padding.Bottom);

            VoronoiResult2D voronoi = Math2D.GetVoronoi(points, true);

            voronoi = Math2D.CapVoronoiCircle(voronoi);
            //voronoi = Math2D.CapVoronoiRectangle(voronoi, aspectRatio: 1d);       //TODO: Implement this

            Canvas canvas = DrawVoronoi_Tiled(voronoi, result.Nodes, result.InputsByNode, size.X.ToInt_Floor(), size.Y.ToInt_Floor(), tileWidth, tileHeight, drawTile, events);

            border.Child = canvas;
        }
        internal static void CreateNeurons(out Neuron_SensorPosition[] neuronsR, out Neuron_SensorPosition[] neuronsG, out Neuron_SensorPosition[] neuronsB, out OverlayResult[][] overlayR, out OverlayResult[][] overlayG, out OverlayResult[][] overlayB, out int pixelWidthHeight, ShipPartDNA dna, ItemOptions itemOptions, double neuronDensity)
        {
            const int MINPIXELWIDTH = 16;

            #region Calculate counts

            // Figure out how many neurons to make
            //NOTE: This radius isn't taking SCALE into account.  The other neural parts do this as well, so the neural density properties can be more consistent
            double radius = (dna.Scale.X + dna.Scale.Y + dna.Scale.Z) / (3d * 2d);		// xyz should all be the same anyway
            double area = Math.Pow(radius, itemOptions.Sensor_NeuronGrowthExponent);

            int neuronCount = Convert.ToInt32(Math.Ceiling(neuronDensity * area));
            if (neuronCount == 0)
            {
                neuronCount = 1;
            }

            // Figure out how many pixels to make
            pixelWidthHeight = neuronCount / 9;     // dividing by 3 to get the number of neurons in a single plate.  divide that by 3, because that's a good ratio of neuron cells to pixels
            if (pixelWidthHeight < MINPIXELWIDTH)
            {
                pixelWidthHeight = MINPIXELWIDTH;
            }

            #endregion

            #region Neurons

            // Place them evenly in a sphere
            //NOTE: An interesting side effect of calling this for each generation is that the parent may not have been perfectly evenly spaced, but calling this
            //again will slightly refine the positions
            Vector3D[][] positions = GetNeuronPositions(dna.Neurons, neuronCount, 3, radius);

            // Create neurons
            neuronsR = positions[0].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray();
            neuronsG = positions[1].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray();
            neuronsB = positions[2].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray();

            #endregion

            #region Polygons around neurons

            // Figure out which pixels each neuron intersects with
            VoronoiResult2D[] voronoi = new VoronoiResult2D[3];
            voronoi[0] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[0].Select(o => new Point(o.X, o.Y)).ToArray(), true));
            voronoi[1] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[1].Select(o => new Point(o.X, o.Y)).ToArray(), true));
            voronoi[2] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[2].Select(o => new Point(o.X, o.Y)).ToArray(), true));

            #region Figure out the extremes

            Point[] allEdgePoints = voronoi.SelectMany(o => o.EdgePoints).ToArray();

            Point min = new Point(allEdgePoints.Min(o => o.X), allEdgePoints.Min(o => o.Y));
            Point max = new Point(allEdgePoints.Max(o => o.X), allEdgePoints.Max(o => o.Y));

            double width = max.X - min.X;
            double height = max.Y - min.Y;

            // Enlarge a bit
            min.X -= width * .05d;
            min.Y -= height * .05d;
            max.X += width * .05d;
            max.Y += height * .05d;

            width = max.X - min.X;
            height = max.Y - min.Y;

            Vector offset = new Vector(-min.X, -min.Y);

            #endregion

            //  Figure out which pixels each polygon overlaps
            overlayR = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[0], offset));
            overlayG = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[1], offset));
            overlayB = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[2], offset));

            #endregion
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
        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 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();
        }
示例#10
0
        internal static void CreateNeurons(out Neuron_SensorPosition[] neuronsR, out Neuron_SensorPosition[] neuronsG, out Neuron_SensorPosition[] neuronsB, out OverlayResult[][] overlayR, out OverlayResult[][] overlayG, out OverlayResult[][] overlayB, out int pixelWidthHeight, ShipPartDNA dna, ItemOptions itemOptions, double neuronDensity)
        {
            const int MINPIXELWIDTH = 16;

            #region Calculate counts

            // Figure out how many neurons to make
            //NOTE: This radius isn't taking SCALE into account.  The other neural parts do this as well, so the neural density properties can be more consistent
            double radius = (dna.Scale.X + dna.Scale.Y + dna.Scale.Z) / (3d * 2d);              // xyz should all be the same anyway
            double area   = Math.Pow(radius, itemOptions.Sensor_NeuronGrowthExponent);

            int neuronCount = Convert.ToInt32(Math.Ceiling(neuronDensity * area));
            if (neuronCount == 0)
            {
                neuronCount = 1;
            }

            // Figure out how many pixels to make
            pixelWidthHeight = neuronCount / 9;     // dividing by 3 to get the number of neurons in a single plate.  divide that by 3, because that's a good ratio of neuron cells to pixels
            if (pixelWidthHeight < MINPIXELWIDTH)
            {
                pixelWidthHeight = MINPIXELWIDTH;
            }

            #endregion

            #region Neurons

            // Place them evenly in a sphere
            //NOTE: An interesting side effect of calling this for each generation is that the parent may not have been perfectly evenly spaced, but calling this
            //again will slightly refine the positions
            Vector3D[][] positions = GetNeuronPositions(dna.Neurons, neuronCount, 3, radius);

            // Create neurons
            neuronsR = positions[0].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray();
            neuronsG = positions[1].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray();
            neuronsB = positions[2].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray();

            #endregion

            #region Polygons around neurons

            // Figure out which pixels each neuron intersects with
            VoronoiResult2D[] voronoi = new VoronoiResult2D[3];
            voronoi[0] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[0].Select(o => new Point(o.X, o.Y)).ToArray(), true));
            voronoi[1] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[1].Select(o => new Point(o.X, o.Y)).ToArray(), true));
            voronoi[2] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[2].Select(o => new Point(o.X, o.Y)).ToArray(), true));

            #region Figure out the extremes

            Point[] allEdgePoints = voronoi.SelectMany(o => o.EdgePoints).ToArray();

            Point min = new Point(allEdgePoints.Min(o => o.X), allEdgePoints.Min(o => o.Y));
            Point max = new Point(allEdgePoints.Max(o => o.X), allEdgePoints.Max(o => o.Y));

            double width  = max.X - min.X;
            double height = max.Y - min.Y;

            // Enlarge a bit
            min.X -= width * .05d;
            min.Y -= height * .05d;
            max.X += width * .05d;
            max.Y += height * .05d;

            width  = max.X - min.X;
            height = max.Y - min.Y;

            Vector offset = new Vector(-min.X, -min.Y);

            #endregion

            //  Figure out which pixels each polygon overlaps
            overlayR = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[0], offset));
            overlayG = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[1], offset));
            overlayB = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[2], offset));

            #endregion
        }
示例#11
0
        private void btn2DCreateLinksSimple_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                PrepFor2D();
                ClearTempVisuals();

                if (_brains2D.Count == 0)
                {
                    return;
                }

                Point[] brainPositions = _brains2D.Select(o => o.Position).ToArray();
                Point[] ioPositions = UtilityCore.Iterate(_inputs2D, _outputs2D).Select(o => o.Position).ToArray();

                //TODO: Don't link every brain to every other brain.  Maybe do a similar voronoi, and only link clusters
                //TODO: It might be interesting to have some brains that are independent of others (only if they are connected to io devices)
                Tuple<int, int>[] brainLinks = Math2D.GetDelaunayTriangulation(brainPositions, chk2DSkipThin.IsChecked.Value, trk2DThinRatio.Value);

                _voronoi2D = Math2D.GetVoronoi(brainPositions, true);

                //TODO: If a brain is over saturated, hand some links to a nearby brain
                //TODO: This method needs to have the logic that spreads out links
                //TODO: Do some random linkage between neighboring cells
                Tuple<int, int>[] ioLinks = Worker2D_Simple.LinkBrainsToIO_Voronoi(_voronoi2D, brainPositions, ioPositions);        //TODO: Don't just take in points.  Need sizes as well

                #region Draw

                // Voronoi lines
                _voronoiLines2D.AddRange(DrawVoronoi(_voronoi2D, _voronoiGrayBrush, 1));

                // Brain-Brain links
                foreach (Tuple<int, int> link in brainLinks)
                {
                    Point from = _brains2D[link.Item1].Position;
                    Point to = _brains2D[link.Item2].Position;

                    UIElement visual = AddLine(from, to, _brainLinkBrush, 2, true);

                    _linksBrain2D.Add(new Item2D(visual, 0, from, to));
                }

                // Brain-IO links
                foreach (Tuple<int, int> link in ioLinks)
                {
                    Point from = _brains2D[link.Item1].Position;
                    Point to = ioPositions[link.Item2];

                    UIElement visual = AddLine(from, to, _ioLinkBrush, isUnder: true);

                    _linksIO2D.Add(new Item2D(visual, 0, from, to));
                }

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private Canvas DrawVoronoi(VoronoiResult2D voronoi, Color[] colors, SOMNode[] nodes, ImageInput[][] images, int imageWidth, int imageHeight)
        {
            const double MARGINPERCENT = 1.05;

            #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();

            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 = new SolidColorBrush(colors[cntr]);
                polygon.Stroke = new SolidColorBrush(UtilityWPF.OppositeColor(colors[cntr], false));
                polygon.StrokeThickness = 1;

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

                polygon.MouseMove += Polygon_MouseMove_OLD;
                polygon.MouseLeave += Polygon_MouseLeave_OLD;

                retVal.Children.Add(polygon);

                #endregion
            }

            return retVal;
        }
示例#13
0
        private static Point[][] GetPolygons(VoronoiResult2D voronoi, Vector offset)
        {
            Point[][] retVal = new Point[voronoi.ControlPoints.Length][];

            for (int cntr = 0; cntr < voronoi.ControlPoints.Length; cntr++)
            {
                retVal[cntr] = voronoi.GetPolygon(cntr, 1).     // don't need to worry about ray length, they are all segments
                    Select(o => o + offset).        // shifting the points by offset
                    ToArray();
            }

            return retVal;
        }
示例#14
0
            private static Tuple<int, int>[] IOLinks_Initial(Set2D[] brains, Item2D[] io, VoronoiResult2D voronoi)
            {
                List<Tuple<int, int>> retVal = new List<Tuple<int, int>>();
                List<int> remainingIO = Enumerable.Range(0, io.Length).ToList();        // store the remaining so that they can be removed as found (avoid unnecessary IsInside checks)

                for (int brainCntr = 0; brainCntr < brains.Length; brainCntr++)
                {
                    Edge2D[] edges = voronoi.EdgesByControlPoint[brainCntr].Select(o => voronoi.Edges[o]).ToArray();

                    if (edges.Length == 1)
                    {
                        throw new ApplicationException("finish this");
                    }

                    foreach (int ioIndex in remainingIO.ToArray())
                    {
                        if (Edge2D.IsInside(edges, io[ioIndex].Position))
                        {
                            retVal.Add(Tuple.Create(brainCntr, ioIndex));
                            remainingIO.Remove(ioIndex);
                        }
                    }
                }

                return retVal.ToArray();
            }
示例#15
0
        private Item2D[] DrawVoronoi(VoronoiResult2D voronoi, Brush brush, double width = 2)
        {
            List<Item2D> retVal = new List<Item2D>();

            // This is used to extend rays, ensure they always go off screen
            double extensionLength = Math.Max(canvas.ActualWidth, canvas.ActualHeight) * 2;

            foreach (Edge2D edge in voronoi.Edges)
            {
                Point from = edge.Point0;
                Point to = edge.GetPoint1Ext(extensionLength);      // if it's a ray, this method will extend it into a segment

                if (edge.EdgeType == EdgeType.Line)
                {
                    // Instead of a ray, make a line
                    from = from + (from - to);
                }

                UIElement visual = AddLine(from, to, brush, width);
                retVal.Add(new Item2D(visual, 0, from, to));
            }

            return retVal.ToArray();
        }
示例#16
0
        private void ClearTempVisuals()
        {
            _voronoi2D = null;

            // 2D
            canvas.Children.RemoveAll(_voronoiLines2D.Select(o => o.Visual));
            _voronoiLines2D.Clear();

            canvas.Children.RemoveAll(_linksBrain2D.Select(o => o.Visual));
            _linksBrain2D.Clear();

            canvas.Children.RemoveAll(_linksIO2D.Select(o => o.Visual));
            _linksIO2D.Clear();

            canvas.Children.RemoveAll(_misc2D.Select(o => o.Visual));
            _misc2D.Clear();

            // 3D
            _viewportFull.Children.RemoveAll(_linksBrain3D.Select(o => o.Visual));
            _linksBrain3D.Clear();

            _viewportFull.Children.RemoveAll(_linksIO3D.Select(o => o.Visual));
            _linksIO3D.Clear();

            _viewportFull.Children.RemoveAll(_misc3D.Select(o => o.Visual));
            _misc3D.Clear();

            _viewportFull.Children.RemoveAll(_voronoiBlob3D.Select(o => o.Visual));
            _voronoiBlob3D.Clear();

            // Stats
            pnlStats.Children.Clear();

            //_voronoi2NeighborData.Clear();
            //btn3DVor2D2Save.IsEnabled = false;
        }
示例#17
0
            public static Tuple<int, int>[] LinkBrainsToIO_Voronoi(VoronoiResult2D voronoi, Point[] brains, Point[] io)
            {
                if (brains.Length == 0)
                {
                    return new Tuple<int, int>[0];
                }
                else if (brains.Length == 1)
                {
                    return Enumerable.Range(0, io.Length).Select(o => Tuple.Create(0, o)).ToArray();
                }

                List<Tuple<int, int>> retVal = new List<Tuple<int, int>>();
                List<int> remainingIO = Enumerable.Range(0, io.Length).ToList();        // store the remaining so that they can be removed as found (avoid unnecessary IsInside checks)

                for (int brainCntr = 0; brainCntr < brains.Length; brainCntr++)
                {
                    Edge2D[] edges = voronoi.EdgesByControlPoint[brainCntr].Select(o => voronoi.Edges[o]).ToArray();

                    if (edges.Length == 1)
                    {
                        throw new ApplicationException("finish this");
                    }

                    foreach (int ioIndex in remainingIO.ToArray())
                    {
                        if (Edge2D.IsInside(edges, io[ioIndex]))
                        {
                            retVal.Add(Tuple.Create(brainCntr, ioIndex));
                            remainingIO.Remove(ioIndex);
                        }
                    }
                }

                return retVal.ToArray();
            }
示例#18
0
        private void btn2DCreateLinksVoronoi_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                PrepFor2D();
                ClearTempVisuals();

                if (_brains2D.Count == 0)
                {
                    return;
                }

                var io = UtilityCore.Iterate(_inputs2D, _outputs2D).ToArray();

                LinkBrain2D[] brainLinks = null;
                LinkIO[] ioLinks = null;

                Worker2D_Voronoi.GetLinks(out brainLinks, out ioLinks, _brains2D.ToArray(), io);

                Point[] brainSetPoints = Math2D.GetUnique(ioLinks.Select(o => o.Brains.Center));
                if (brainSetPoints.Length > 1)
                {
                    _voronoi2D = Math2D.GetVoronoi(brainSetPoints, true);       // this is redundant, since the worker has to get this too, but it's just a tester, and I don't want to complicate the interface
                }

                #region Draw

                // Voronoi lines
                if (_voronoi2D != null)
                {
                    _voronoiLines2D.AddRange(DrawVoronoi(_voronoi2D, _voronoiGrayBrush, 1));
                }

                //TODO: Represent the number of links between two items as line thickness

                // Brain-Brain links
                if (brainLinks != null)
                {
                    foreach (var link in brainLinks)
                    {
                        // Group From
                        if (link.Brains1.Items.Length > 1)
                        {
                            _linksBrain2D.Add(DrawBrainGroup(link.Brains1.Positions, link.Brains2.Center));
                        }

                        // Group To
                        if (link.Brains2.Items.Length > 1)
                        {
                            _linksBrain2D.Add(DrawBrainGroup(link.Brains2.Positions, link.Brains2.Center));
                        }

                        // Link
                        UIElement visual = AddLine(link.Brains1.Center, link.Brains2.Center, _brainLinkBrush);

                        _linksBrain2D.Add(new Item2D(visual, 0, link.Brains1.Center, link.Brains2.Center));
                    }
                }

                // Brain-IO links
                if (ioLinks != null)
                {
                    foreach (var link in ioLinks)
                    {
                        // Group From
                        if (link.Brains.Items.Length > 1)
                        {
                            _linksIO2D.Add(DrawBrainGroup(link.Brains.Positions, link.Brains.Center));
                        }

                        // Link
                        UIElement visual = AddLine(link.Brains.Center, link.IO.Position, _ioLinkBrush, isUnder: true);

                        _linksIO2D.Add(new Item2D(visual, 0, link.Brains.Center, link.IO.Position));
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        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;
        }
示例#20
0
        private void btn2DVoronoiBrains_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                PrepFor2D();
                ClearTempVisuals();

                if (_brains2D.Count == 0)
                {
                    return;
                }

                _voronoi2D = Math2D.GetVoronoi(_brains2D.Select(o => o.Position).ToArray(), true);

                _voronoiLines2D.AddRange(DrawVoronoi(_voronoi2D, Brushes.Black));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }