Exemplo n.º 1
0
        //private object syncLock = new object();
        public QuadTree(Rectangle2 screenSize, int[] pixels, int minTileHeight = 64, int minTileWidth = 64)
        {
            var t = Stopwatch.StartNew();

            QuadNode.MIN_HEIGHT = minTileHeight; //Any better way ?
            QuadNode.MIN_WIDTH  = minTileWidth;

            ScreenSize     = screenSize;
            ScreenPixels   = pixels;
            LocationToNode = new Dictionary <Rectangle2, QuadNode>();

            Root = new QuadNode(screenSize, pixels);

            //Very time consuming method ! Needs optimization
            //Root.Expand();

            var a           = Stopwatch.StartNew();
            var lowestLevel = BFSLowest();

            a.Stop();
            Trace.WriteLine("Found lowest in:" + a.ElapsedMilliseconds + "ms");

            a = Stopwatch.StartNew();
            var numberOfTasks = lowestLevel.Count * 4;
            var signal        = new ManualResetEvent(false);

            var arr = lowestLevel.ToArray();

            for (var iter = 0; iter < arr.Length; iter++)
            {
                var currNode = arr[iter];
                for (var i = 0; i < 4; i++)
                {
                    var li = i;
                    //ThreadPool.QueueUserWorkItem(func =>
                    //{
                    var  occurances = new Dictionary <int, long>();
                    long h          = 1;
                    long maxO       = -1;
                    long maxV       = -1;

                    for (long j = 0; j < currNode.childrenData[li].Length; j++)
                    {
                        var px = currNode.childrenData[li][j];
                        h = h * ((px + j) % QuadNode.Q) % QuadNode.Q;

                        var val = px;
                        if (!occurances.ContainsKey(val))
                        {
                            occurances.Add(val, 0);
                        }
                        occurances[val]++;

                        if (occurances[val] > maxO)
                        {
                            maxO = occurances[val];
                            maxV = val;
                        }
                    }

                    currNode.childrenHashes[li] = h;
                    long diff = occurances.Count;

                    //Calculates the percentage of different pixels in the rectangle
                    //If it is less than 10 in 1024, the tile is considered to be filled with a solid color
                    //The solid color used for filling is the color which occured the most times
                    var percDiff = (float)diff / currNode.childrenData[li].Length;
                    if (percDiff < 0.01)
                    {
                        currNode.childrenRect[li].SetSolidColor((int)maxV);
                        currNode.childrenHashes[li] = (long)Math.Pow(maxV * maxO * diff, 3) % QuadNode.Q;
                        //idk if the previous hash would be better or this one
                    }
                    currNode.DataHash = (currNode.DataHash + currNode.childrenHashes[li]) % QuadNode.Q;

                    if (Interlocked.Decrement(ref numberOfTasks) == 0)
                    {
                        signal.Set();
                    }
                    //});
                }
            }
            signal.WaitOne();
            a.Stop();
            Trace.WriteLine("Processed nodes in:" + a.ElapsedMilliseconds + "ms");

            Root.CalculateHash();
            //IEnumerable<QuadNode> nodes = GetChildren(Root);
            //foreach (QuadNode ch in nodes)
            //{
            //LocationToNode.Add(ch.Bounds, ch);
            //}
            t.Stop();
            Trace.WriteLine("QuadTree construction: " + t.ElapsedMilliseconds + "ms");
        }