public EncodedRectangle Build(QuadNode node, VncHost.Encoding encoding) { int[] pixels = node.NodeData; EncodedRectangle e; switch (encoding) { case VncHost.Encoding.RawEncoding: e = new RawRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.CopyRectEncoding: e = new CopyRectRectangle(rfb, framebuffer, node.Bounds); break; case VncHost.Encoding.RreEncoding: e = new RreRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.CoRreEncoding: e = new CoRreRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.HextileEncoding: e = new HextileRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.ZrleEncoding: e = new ZrleRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.ZlibEncoding: e = new ZlibRectangle(rfb, framebuffer, pixels, node.Bounds); break; default: // Sanity check throw new Exception("Unsupported Encoding Format received: " + encoding + "."); } return e; }
private void AddQuadObjectToNode(QuadNode node, T quadObject) { lock (syncLock) { try { objectToNodeLookup.Add(quadObject, node); node.quadObjects.Add(quadObject); //quadObject.BoundsChanged += new EventHandler(quadObject_BoundsChanged); } catch (ArgumentException) { // Do nothing, this means we are simply dealing with duplicate CIM_PositionPoints. } } }
/// <summary> /// Walk the given linked list and test each node against the given bounds/ /// </summary> /// <param name="last">The last node in the circularly linked list.</param> /// <param name="bounds">Bounds to test</param> /// <returns>Return true if a node in the list intersects the bounds</returns> static bool HasIntersectingNodes(QuadNode last, Rect bounds) { if (last != null) { QuadNode n = last; do { n = n.Next; // first node. if (n.Bounds.IntersectsWith(bounds)) { return(true); } } while (n != last); } return(false); }
private int GetQuadObjectCount(QuadNode node) { //lock (syncLock) //{ int count = node.Objects.Count; foreach (QuadNode childNode in node.Nodes) { if (childNode != null) { count += GetQuadObjectCount(childNode); } } return(count); //} }
private int GetQuadNodeCount(QuadNode <T> node, int count) { if (node == null) { return(count); } foreach (var childNode in node.Nodes) { if (childNode != null) { count++; } } return(count); }
private int GetQuadObjectCount(QuadNode node) { lock (syncLock) { var count = node.Objects.Count; foreach (var childNode in node.Nodes) { if (childNode != null) { count += GetQuadObjectCount(childNode); } } return(count); } }
private List <T> GetChildObjects(QuadNode node) { lock (syncLock) { List <T> results = new List <T>(); results.AddRange(node.quadObjects); foreach (QuadNode childNode in node.Nodes) { if (childNode != null) { results.AddRange(GetChildObjects(childNode)); } } return(results); } }
/// <summary> /// move toward the current cell /// </summary> /// <returns></returns> private BehaviorReturnCode moveTowardsCell() { //get positions, velocity, and heading Position mePos = (Position)s_PositionMapper.get(s_ThisEntity); Velocity meVel = (Velocity)s_VelocityMapper.get(s_ThisEntity); Heading meHeading = (Heading)s_HeadingMapper.get(s_ThisEntity); //get current pos Vector2 pos = mePos.Pos;// +s_Offset; Vector2 vec = new Vector2(s_CurrentCell.Position.X * s_TileSize, s_CurrentCell.Position.Y * s_TileSize); //check for condition that could cause a not-a-number exception //if ((vec - s_Center) == pos) if ((vec) == pos) { return(BehaviorReturnCode.Success); } //create heading from this entityt to targetNode //vec = Vector2.Subtract(vec - s_Center, pos); vec = Vector2.Subtract(vec, pos); vec.Normalize(); //set heading meHeading.setHeading(Vector2.Multiply(vec, meVel.Vel)); //update position pos += meHeading.getHeading(); mePos.Pos = pos; s_moved = true; SpatialPartition spatial = (SpatialPartition)s_SpatialMapper.get(s_Spatial); //remove old reference if (s_LastNode != null) { s_LastNode.Contents.Remove(s_ThisEntity); } //set new position and get new reference spatial.QuadTree.setContentAtLocation(s_ThisEntity, pos); s_LastNode = spatial.QuadTree.locateNode(pos); return(BehaviorReturnCode.Success); }
private void InsertNodeObject(QuadNode node, T quadObject) { lock (syncLock) { if (!node.BBox.Contains(quadObject.GetBBox())) { throw new Exception("This should not happen, child does not fit within node bounds"); } if (!node.HasChildNodes() && node.Objects.Count + 1 > maxObjectsPerLeaf) { SetupChildNodes(node); List <T> childObjects = new List <T>(node.Objects); List <T> childrenToRelocate = new List <T>(); foreach (T childObject in childObjects) { foreach (QuadNode childNode in node.Nodes) { if (childNode == null) { continue; } if (childNode.BBox.Contains(childObject.GetBBox())) { childrenToRelocate.Add(childObject); } } } foreach (T childObject in childrenToRelocate) { RemoveQuadObjectFromNode(childObject); InsertNodeObject(node, childObject); } } foreach (QuadNode childNode in node.Nodes) { if (childNode != null) { if (childNode.BBox.Contains(quadObject.GetBBox())) { InsertNodeObject(childNode, quadObject); return; } } } AddQuadObjectToNode(node, quadObject); } }
void Start() { SoI = Mathd.Sqrt(Gravity.G * mass / .0001); double s = 1.41421356237 * radius; Vector3d[] v = new Vector3d[] { Vector3d.up, Vector3d.down, Vector3d.left, Vector3d.right, Vector3d.forward, Vector3d.back }; Quaterniond[] q = new Quaterniond[] { Quaterniond.Euler(0, 0, 0), Quaterniond.Euler(180, 0, 0), Quaterniond.Euler(0, 0, 90), Quaterniond.Euler(0, 0, -90), Quaterniond.Euler(90, 0, 0), Quaterniond.Euler(-90, 0, 0) }; groundNodes = new QuadNode[6]; if (hasWater) { waterNodes = new QuadNode[6]; } for (int i = 0; i < 6; i++) { groundNodes[i] = new QuadNode(this, QuadNode.SurfaceType.Ground, 0, s, 0, null, s * .5 * v[i], q[i]); if (hasWater) { waterNodes[i] = new QuadNode(this, QuadNode.SurfaceType.Water, 0, s, 0, null, s * .5 * v[i], q[i]); } } simplex = new Simplex() { seed = seed }; InitPropertyBlock(); started = true; }
private void SetupChildNodes(QuadNode <T> node) { if (minLeafSize.X <= node.Bounds.Width / 2 && minLeafSize.Y <= node.Bounds.Height / 2) { node[EDirection.NW] = new QuadNode <T>(node.Bounds.X, node.Bounds.Y, node.Bounds.Width / 2, node.Bounds.Height / 2); node[EDirection.NE] = new QuadNode <T>(node.Bounds.X + node.Bounds.Width / 2, node.Bounds.Y, node.Bounds.Width / 2, node.Bounds.Height / 2); node[EDirection.SW] = new QuadNode <T>(node.Bounds.X, node.Bounds.Y + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); node[EDirection.SE] = new QuadNode <T>(node.Bounds.X + node.Bounds.Width / 2, node.Bounds.Y + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); } }
protected override void process(Entity entity) { Position position = (Position)q_PositionMapper.get(entity); ViewPort camera = (ViewPort)q_ViewPortMapper.get(q_Camera); SpatialPartition spatial = (SpatialPartition)q_SpatialMapper.get(q_Spatial); Vector2 pos = position.Pos + position.Offset; Vector2 origin = camera.getOrigin(); QuadNode <Entity> node = spatial.QuadTree.locateNode(pos); int width = (int)(node.LRCorner.X - node.ULCorner.X); int height = (int)(node.LRCorner.Y - node.ULCorner.Y); Rectangle rec = new Rectangle((int)(node.ULCorner.X - origin.X), (int)(node.ULCorner.Y - origin.Y), width, height); _sprite_batch.Draw(q_Texture, rec, new Color(1f, 0f, 0f, 0f)); }
public void Awake() { allQuadNode = new List <QuadNode>(); RootNode = new QuadNode(0, 0, null, new Vector3Int(5, 5, 0), new Vector3Int(517, 517, 0)); int count = RSSPosition.Count; for (int i = 0; i < count; i++) { RootNode.Insert(RSSPosition.ReadOnlyRows[i].Position.Parse3Int().ToClientPosition()); } RootNode.AllChildren(allQuadNode); }
void SaveQuadTree(QuadNode node, StringBuilder builder, List <ISelectableObject> allObjects) { builder.Append(node.Id); builder.Append("\t"); builder.Append(node.X); builder.Append("\t"); builder.Append(node.Y); builder.Append("\t"); builder.Append(node.Width); builder.Append("\t"); builder.Append(node.Height); if (node.TL != null) { builder.Append("\t"); builder.Append(4); builder.Append("\t"); builder.Append(0); builder.AppendLine(); SaveQuadTree(node.TL, builder, allObjects); SaveQuadTree(node.TR, builder, allObjects); SaveQuadTree(node.BL, builder, allObjects); SaveQuadTree(node.BR, builder, allObjects); } else if (node.Objects != null) { builder.Append("\t"); builder.Append(0); builder.Append("\t"); builder.Append(node.Objects.Count); foreach (GameObject obj in node.Objects) { builder.Append("\t"); builder.Append(allObjects.IndexOf(obj)); } builder.AppendLine(); } else { builder.Append("\t"); builder.Append(0); builder.Append("\t"); builder.Append(0); builder.AppendLine(); } }
private int GetQuadNodeCount(QuadNode node, int count) { lock (syncLock) { if (node == null) { return(count); } foreach (QuadNode childNode in node.Nodes) { if (childNode != null) { count++; } } return(count); } }
/// <summary> /// grows a tree of n-tiers from current node /// </summary> /// <param name="node">node to grow from</param> /// <param name="tiers">number of tiers to grow</param> private void grow_tree(QuadNode<E> node, int tiers) { if (tiers == 0) { return; } else { node.Q1.subdivide(); grow_tree(node.Q1, tiers - 1); node.Q2.subdivide(); grow_tree(node.Q2, tiers - 1); node.Q3.subdivide(); grow_tree(node.Q3, tiers - 1); node.Q4.subdivide(); grow_tree(node.Q4, tiers - 1); } }
public bool HasNodesIntersecting(Rect bounds) { QuadNode quadNode = this; while (true) { quadNode = quadNode.Next; if (bounds.Intersects(quadNode.Bounds)) { break; } if (quadNode == this) { return(false); } } return(true); }
public bool HasNodesInside(Rect bounds) { QuadNode quadNode = this; while (true) { quadNode = quadNode.Next; if (bounds.Contains(quadNode.Bounds)) { break; } if (quadNode == this) { return(false); } } return(true); }
private BehaviorReturnCode initializePathfinder() { Position start = (Position)s_PositionMapper.get(s_ThisEntity); Position finish = (Position)s_PositionMapper.get(s_Target); s_Map = s_EcsInstance.tag_manager.get_entity_by_tag("MAP"); GameMap map = (GameMap)s_GameMapMapper.get(s_Map); s_Camera = s_EcsInstance.tag_manager.get_entity_by_tag("CAMERA"); ViewPort viewport = (ViewPort)s_ViewPortMapper.get(s_Camera); s_Spatial = s_EcsInstance.tag_manager.get_entity_by_tag("SPATIAL"); SpatialPartition spatial = (SpatialPartition)s_SpatialMapper.get(s_Spatial); spatial.QuadTree.setContentAtLocation(s_ThisEntity, start.Pos); s_LastNode = spatial.QuadTree.locateNode(start.Pos); Vector2 sVec, fVec; //s_Center = viewport.getDimensions() / 2; sVec = (start.Pos) / s_TileSize; fVec = (finish.Pos + finish.Offset) / s_TileSize; /* * sVec = (start.Pos + s_Center) / s_TileSize; * fVec = (finish.Pos + s_Center) / s_TileSize; */ s_TargetCell.Position = fVec; s_CurrentCell.Position = sVec; findPath = new FindPathAction(s_EcsInstance, sVec, fVec, map); s_TargetCurrentPosition = finish.Pos + s_Offset; //convert to map position s_TargetCurrentPosition = new Vector2((int)s_TargetCurrentPosition.X / s_TileSize, (int)s_TargetCurrentPosition.Y / s_TileSize); s_TargetPreviousPosition = s_TargetCurrentPosition; s_BeginPathingAndMovement = true; return(BehaviorReturnCode.Success); }
public void Dump(LogWriter w) { w.WriteAttribute("Bounds", _bounds.ToString()); if (_nodes != null) { QuadNode n = _nodes; do { n = n.Next; // first node. w.Open("node"); w.WriteAttribute("Bounds", n.Bounds.ToString()); w.Close(); } while (n != _nodes); } DumpQuadrant("TopLeft", _topLeft, w); DumpQuadrant("TopRight", _topRight, w); DumpQuadrant("BottomLeft", _bottomLeft, w); DumpQuadrant("BottomRight", _bottomRight, w); }
/// <summary> /// locates a leaf node descendant of the current node that contains the given point /// </summary> /// <param name="node">node being searched</param> /// <param name="point">point searched for</param> /// <returns>leaf node containing the point</returns> private QuadNode<E> locateNode(QuadNode<E> node, Vector2 point) { if (node.Q1 == null || node.Q2 == null || node.Q3 == null || node.Q4 == null) { return node; } else { if (node.Q1.contains(point)) return locateNode(node.Q1, point); if (node.Q2.contains(point)) return locateNode(node.Q2, point); if (node.Q3.contains(point)) return locateNode(node.Q3, point); if (node.Q4.contains(point)) return locateNode(node.Q4, point); return null; } }
void InitializeQuadTree() { double s = 1.41421356237 * Radius; VisibleNodes = new List <QuadNode>(); BaseNodes = new QuadNode[6]; BaseNodes[0] = new QuadNode(this, 0, s, 0, null, s * .5f * (Vector3d)Vector3.Up, MathTools.RotationXYZ(0, 0, 0)); BaseNodes[1] = new QuadNode(this, 1, s, 0, null, s * .5f * (Vector3d)Vector3.Down, MathTools.RotationXYZ(MathUtil.Pi, 0, 0)); BaseNodes[2] = new QuadNode(this, 2, s, 0, null, s * .5f * (Vector3d)Vector3.Left, MathTools.RotationXYZ(0, 0, MathUtil.PiOverTwo)); BaseNodes[3] = new QuadNode(this, 3, s, 0, null, s * .5f * (Vector3d)Vector3.Right, MathTools.RotationXYZ(0, 0, -MathUtil.PiOverTwo)); BaseNodes[4] = new QuadNode(this, 4, s, 0, null, s * .5f * (Vector3d)Vector3.ForwardLH, MathTools.RotationXYZ(MathUtil.PiOverTwo, 0, 0)); BaseNodes[5] = new QuadNode(this, 5, s, 0, null, s * .5f * (Vector3d)Vector3.BackwardLH, MathTools.RotationXYZ(-MathUtil.PiOverTwo, 0, 0)); for (int i = 0; i < BaseNodes.Length; i++) { BaseNodes[i].Generate(); } }
public void Remove(T quadObject) { lock (syncLock) { if (sort && objectSortOrder.ContainsKey(quadObject)) { objectSortOrder.Remove(quadObject); } if (!objectToNodeLookup.ContainsKey(quadObject)) { throw new KeyNotFoundException("QuadObject not found in dictionary for removal"); } QuadNode containingNode = objectToNodeLookup[quadObject]; RemoveQuadObjectFromNode(quadObject); if (containingNode.Parent != null) { CheckChildNodes(containingNode.Parent); } } }
private void SetupChildNodes(QuadNode node) { //lock (syncLock) { if (minLeafSize.X <= node.Bounds.Width / 2 && minLeafSize.Y <= node.Bounds.Height / 2) { node[Direction.NW] = new QuadNode(node.Bounds.X0, node.Bounds.Y0, node.Bounds.Width / 2, node.Bounds.Height / 2); node[Direction.NE] = new QuadNode(node.Bounds.X0 + node.Bounds.Width / 2, node.Bounds.Y0, node.Bounds.Width / 2, node.Bounds.Height / 2); node[Direction.SW] = new QuadNode(node.Bounds.X0, node.Bounds.Y0 + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); node[Direction.SE] = new QuadNode(node.Bounds.X0 + node.Bounds.Width / 2, node.Bounds.Y0 + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); } } }
private void SetupChildNodes(QuadNode node) { lock (syncLock) { if (minLeafSizeF.X <= node.Bounds.Width / 2 && minLeafSizeF.Y <= node.Bounds.Height / 2) { node[DiRectangleFion.NW] = new QuadNode(node.Bounds.Left, node.Bounds.Top, node.Bounds.Width / 2, node.Bounds.Height / 2); node[DiRectangleFion.NE] = new QuadNode(node.Bounds.Left + node.Bounds.Width / 2, node.Bounds.Top, node.Bounds.Width / 2, node.Bounds.Height / 2); node[DiRectangleFion.SW] = new QuadNode(node.Bounds.Left, node.Bounds.Top + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); node[DiRectangleFion.SE] = new QuadNode(node.Bounds.Left + node.Bounds.Width / 2, node.Bounds.Top + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); } } }
private void SetupChildNodes(QuadNode node) { lock (syncLock) { if (minLeafSize.Width <= node.Bounds.Width / 2 && minLeafSize.Height <= node.Bounds.Height / 2) { node[QuadDirection.NW] = new QuadNode(node.Bounds.X, node.Bounds.Y, node.Bounds.Width / 2, node.Bounds.Height / 2); node[QuadDirection.NE] = new QuadNode(node.Bounds.X + node.Bounds.Width / 2, node.Bounds.Y, node.Bounds.Width / 2, node.Bounds.Height / 2); node[QuadDirection.SW] = new QuadNode(node.Bounds.X, node.Bounds.Y + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); node[QuadDirection.SE] = new QuadNode(node.Bounds.X + node.Bounds.Width / 2, node.Bounds.Y + node.Bounds.Height / 2, node.Bounds.Width / 2, node.Bounds.Height / 2); } } }
void quadObject_BoundsChanged(object sender, EventArgs e) { lock (syncLock) { T quadObject = sender as T; if (quadObject != null) { QuadNode node = objectToNodeLookup[quadObject]; if (!node.Bounds.Contains(quadObject.Bounds.Rectangle) || node.HasChildNodes()) { RemoveQuadObjectFromNode(quadObject); Insert(quadObject); if (node.Parent != null) { CheckChildNodes(node.Parent); } } } } }
public static void SetQuadNode(Type type, IQuadNodeReferring unit, QuadNode newNode) { if (type == typeof(CollisionManager)) { ((ICollidable)unit).SetQuadNodeForCollision(newNode); } else if (type == typeof(PlayerFogManager)) { ((IVisible)unit).SetQuadNodeForPlayerVisibility(newNode); } else if (type == typeof(PcFogManager)) { ((IVisible)unit).SetQuadNodeForPcVisibility(newNode); } else { throw new Exception("Unknown QuadNode user!"); } }
public static void Dump <T>(this Quadrant <T> source, LogWriter w) where T : class { w.WriteAttribute("Bounds", source.Bounds.ToString()); if (source.Nodes != null) { QuadNode <T> n = source.Nodes; do { n = n.Next; // first node. w.Open("node"); w.WriteAttribute("Bounds", n.Bounds.ToString()); w.Close(); } while (n != source.Nodes); } DumpQuadrant("TopLeft", source.TopLeft, w); DumpQuadrant("TopRight", source.TopRight, w); DumpQuadrant("BottomLeft", source.BottomLeft, w); DumpQuadrant("BottomRight", source.BottomRight, w); }
private void ReleaseQuadNode(QuadNode quadNode) { ReadOnlyCollection <Vector3Int> rssClientPosition = quadNode.Points; //Debugger.Log("release count " + rssClientPosition.Count); for (int i = 0; i < rssClientPosition.Count; i++) { try { //rssClientPosition.Log(" - "); RSS_PositionRow rss = RSSPositionTable.GetRssAt(rssClientPosition[i].ToSerPosition()); int id = rss != null ? rss.ID : -1; ReturnRSS(id); } catch (Exception e) { Debugger.Log(e.ToString()); } } }
public EncodedRectangle Build(QuadNode node, VncHost.Encoding encoding) { var pixels = node.NodeData; EncodedRectangle e; switch (encoding) { case VncHost.Encoding.RawEncoding: e = new RawRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.CopyRectEncoding: e = new CopyRectRectangle(rfb, framebuffer, node.Bounds); break; case VncHost.Encoding.RreEncoding: e = new RreRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.CoRreEncoding: e = new CoRreRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.HextileEncoding: e = new HextileRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.ZrleEncoding: e = new ZrleRectangle(rfb, framebuffer, pixels, node.Bounds); break; case VncHost.Encoding.ZlibEncoding: e = new ZlibRectangle(rfb, framebuffer, pixels, node.Bounds); break; default: // Sanity check throw new Exception("Unsupported Encoding Format received: " + encoding + "."); } return(e); }
private int GetQuadObjectCount(QuadNode node) { lock (syncLock) { if (node.IsLeaf) { return(node.Objects.Count); } var count = 0; foreach (var childId in node.ChildIds) { var childNode = Nodes[childId]; if (childNode != null) { count += GetQuadObjectCount(childNode); } } return(count); } }
private HashSet<QuadNode> BFSLowest() { var ret = new HashSet<QuadNode>(); var q = new Queue<QuadNode>(); q.Enqueue(Root); while (q.Count > 0) { var c = q.Dequeue(); if (c.CanExpand()) { for (var i = 0; i < 4; i++) { var li = i; var d = (Direction) li; c[d] = new QuadNode(c.childrenRect[li], c.childrenData[li]); q.Enqueue(c[d]); } } else { ret.Add(c); } } return ret; }
private bool SaveQuadTreeObject(QuadNode root, StreamWriter strWriter) { if (root == null) return false; //write object's information List<Item> allItem = root.GetAllObjects(); for (int i = 0; i < allItem.Count; i++) { strWriter.WriteLine("" + root.Id + " " // node id + allItem[i].ItemInfoID + " " // item id + allItem[i].ItemRectangle.X + " " // position X + allItem[i].ItemRectangle.Y + " " // position Y + allItem[i].ItemRectangle.Width + " " // partition width + allItem[i].ItemRectangle.Height // partition height ); } if (root.NodeLT != null) SaveQuadTreeObject(root.NodeLT, strWriter); // save objects in left-top node if (root.NodeLB != null) SaveQuadTreeObject(root.NodeLB, strWriter); // save objects in left-bottom node if (root.NodeRB != null) SaveQuadTreeObject(root.NodeRB, strWriter); // save objects in right-bottom node if (root.NodeRT != null) SaveQuadTreeObject(root.NodeRT, strWriter); // save objects in right-top node return true; }
private bool SaveQuadTreeNode(QuadNode root, StreamWriter strWriter) { if (root == null) return false; //write node's information strWriter.WriteLine("" + root.Id + " " // root id + root.Partition.X + " " // position X + root.Partition.Y + " " // position Y + root.Partition.Width + " " // partition width + root.Partition.Height // partition height ); if (root.NodeLT != null) SaveQuadTreeNode(root.NodeLT, strWriter); // save left-top node if (root.NodeLB != null) SaveQuadTreeNode(root.NodeLB, strWriter); // save left-bottom node if (root.NodeRB != null) SaveQuadTreeNode(root.NodeRB, strWriter); // save right-bottom node if (root.NodeRT != null) SaveQuadTreeNode(root.NodeRT, strWriter); // save right-top node return true; }
private IEnumerable<QuadNode> GetChildren(QuadNode root) { var ret = new HashSet<QuadNode>(); GetChildren(root, ret); return ret; }
private void GetChildren(QuadNode root, ICollection<QuadNode> ret) { if (root != null) { ret.Add(root); for (var i = 0; i < 4; i++) { var ch = root[(Direction) i]; if (ch != null) { GetChildren(ch, ret); } } } }
//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"); }