Example #1
0
		/**
		 * Find node that contain element
		 * 
		 * Return QuadtreeNode that has element
		 **/
		public QuadtreeNode FindNode(IQuadtreeAgent element){

			if (element == null)
				return null;

			if (boundary.ContainPoint2D (element.GetCenter()) == CollisionResult.None) {

				//element never added to quadtree
				#if DEBUG
				Debug.LogWarning("Unable to find element, element never exist under this quadtree node");
				#endif

				return null;
			}


			//Search child node that contain element position
			if (nodes != null) {

				int nodeIndex = IndexOfNode (element);

				//also check element boundary within node boundary
				if (nodeIndex >= 0 
					&& (element.GetShape().IntersectWithShape(nodes[nodeIndex].boundary) == CollisionResult.Fit))
					return nodes [nodeIndex].FindNode(element);
			}

			if (elements.Contains (element) || overlapElements.Contains (element))
				return this;

			//Something went wrong element within boundary but not in list
			return null;

		}
Example #2
0
		/**
		 * Find possible elements that might contact with given element
		 * from root node
		 * 
		 * Param includeSelf is true given element might be in the result, default is false
		 **/
		public List<IQuadtreeAgent> FindElementsFromRoot(IQuadtreeAgent element, bool includeSelf = false){

			//If not root then find root and find elements
			if (parentNode != null)
				return rootQuadtree ().FindElements (element, includeSelf);

			return FindElements (element, includeSelf);
		}
Example #3
0
		/**
		 * Find element from root quadtree
		 * 
		 * Return QuadtreeNode that has element
		 **/
		public QuadtreeNode FindNodeFromRoot(IQuadtreeAgent element){

			if (element == null)
				return null;

			//If this quadtree is not root
			if (parentNode != null)
				return rootQuadtree ().FindNode (element);

			return FindNode (element);
		}
Example #4
0
		/**
		 * Remove element under this quadtree node
		 **/
		public bool Remove(IQuadtreeAgent element){

			bool removed = false;

			//If element in this node then remove it
			if (elements.Contains (element) || overlapElements.Contains (element)) {
			
				elements.Remove (element);
				overlapElements.Remove (element);

				removed = true;
			}

			if (!removed) {

				//search child
				if(nodes != null){

					int nodeIndex = IndexOfNode (element);

					if (nodeIndex >= 0) {

						CollisionResult r = element.GetShape().IntersectWithShape (nodes [nodeIndex].boundary);

						switch (r) {

						case CollisionResult.Fit://can only fit in one child node
							removed = nodes [nodeIndex].Remove (element);
							break;
						}
					}
				}
			}

			if (removed == true)
				organizeTree = true;

			#if DEBUG
			if(!removed)
				Debug.LogError("Can not remove element");
			#endif

			return removed;
		}
Example #5
0
		/**
		 * Return index of child node under this node
		 * 
		 * This is noly check for element's positon not boundary
		 * 
		 * Return -1 if not found
		 **/
		int IndexOfNode(IQuadtreeAgent element){

			if ((element == null) || (nodes == null))
				return -1;

			IEnumerator er = nodes.GetEnumerator ();
			int nodeIndex = 0;
			while (er.MoveNext ()) {
			
				if ((er.Current as QuadtreeNode).boundary.ContainPoint2D (element.GetCenter ()) != CollisionResult.None) {

					return nodeIndex;
				}

				nodeIndex++;
			}

			#if DEBUG
			Debug.LogError("Element "+((QtAgent)element).agGameObject.name+" does not located in this node fix me");
			#endif

			return -1;
		}
Example #6
0
		/**
		 * Find elements that might contact with given element
		 * under this node.
		 * 
		 * 
		 * Param includeSelf is true given element might be in the result, default is false
		 * 
		 * Param upwardSearch true query will find the node that query shape complete fit in  in first
		 * place then start search downward from that node. It is recommend to leave value as true for 
		 * more accurate result.
		 * 
		 * Param compare a function you can provide and do addition check base on result it found
		 **/
		public List<IQuadtreeAgent> FindElements(IQuadtreeAgent element, bool upwardSearch = true, bool includeSelf = false, OnCompare compare = null){

			if (element == null) {

				#if DEBUG
				Debug.LogError("Can't find elements, given element is null");
				#endif
				return null;
			}

			/**
			 * Upward search from this node
			 * 
			 * This will go up until the node wihch element shape complete fit in
			 **/
			if (upwardSearch) {

				//If this is the node element shape complete fit in
				CollisionResult cResult = element.GetShape().IntersectWithShape(boundary);

				//we found the node then start from this node
				if (cResult == CollisionResult.Fit) {

					//downward search from parent if there is parent node
					//the reason from parent node is that parent node's overlap element
					//might be contact this shape
					if (parentNode != null) {

						//from parent node we start downward search
						return parentNode.FindElements (element, false, includeSelf, compare);
					}

				} else {//continue search upward

					//If there is a parent node otherwsie this is root node and start from
					//here downward search
					if (parentNode != null) {

						//Continue finding upward until the node element shape can totally fit in
						return parentNode.FindElements (element, true, includeSelf, compare);
					}
				}

			}

			/**
			 * Downward search from this node
			 * 
			 * Downward search only search elements in child node include this node
			 **/

			List<IQuadtreeAgent> result = new List<IQuadtreeAgent> ();

			CollisionResult r = element.GetShape ().IntersectWithShape (boundary);

			//if not contact with element shape 
			if (r == CollisionResult.None)
				return result;

			//search child nodes
			IEnumerator er = nodes.GetEnumerator();
			while (er.MoveNext ()) {
			
				//downward search child
				result.AddRange ((er.Current as QuadtreeNode).FindElements (element, false, includeSelf, compare));
			}

			//add this node's elements
			result.AddRange (elements);
			result.AddRange (overlapElements);


			if (!includeSelf) {
				result.Remove (element);
			}

			if (compare != null) {
				
				List<IQuadtreeAgent> filterResult = new List<IQuadtreeAgent>();

				List<IQuadtreeAgent>.Enumerator qer = result.GetEnumerator ();
				while (qer.MoveNext ()) {
				
					if (compare (qer.Current))
						filterResult.Add (qer.Current);
				}

				return filterResult;
			}
				
			return result;

		}
Example #7
0
		/**
		 * Add element to quadtree immediately under this
		 * quadtree node or deeper child node
		 **/
		public bool Add(IQuadtreeAgent newElement){

			if (newElement == null) {
			
				#if DEBUG
				Debug.LogError("Node does not implement IQuadtree");
				#endif
				return false;
			}

			//If we have child node
			if (nodes != null) {

				int nodeIndex = IndexOfNode (newElement);

				//can't find index of node
				if (nodeIndex < 0) {

					#if DEBUG
					Debug.LogError("No child node found"+" node boundary center "+this.boundary.Center
						+ "level "+Depth 
						+" xMin " + boundary.xMin + " xMax "+boundary.xMax
						+" yMin " + boundary.yMin + " yMax "+boundary.yMax
						+" element center "+newElement.GetCenter()
						+ " element last center "+ (newElement as QtAgent).lastPosition);
					#endif
					return false;
				}

				//check if element's boundary fit in the 
				//child node otherwise element is overlapping multiple node
				CollisionResult iResult = newElement.GetShape().IntersectWithShape(nodes[nodeIndex].boundary);

				switch (iResult) {
				case CollisionResult.Fit:
					//Element's boudnary fit in child node's boundary, add it to child node
					return nodes [nodeIndex].Add (newElement);

				case CollisionResult.Overlap:
					
					//Element's boudnary overlap multiple child node, add it to this node
					overlapElements.Add (newElement);
					//notify element it has been added to this quadtree node
					newElement.AddToQuadtreeNode (this);
					return true;

				case CollisionResult.None:
					//Element's boundary not intersect with child node
					//Something went wrong
					#if DEBUG
					Debug.LogError("Unable to add element, element position within node but not intersect with any child node");
					#endif
					return false;
				}

				return false;
			}
				
			elements.Add (newElement);

			//notify element it has been added to this quadtree node
			newElement.AddToQuadtreeNode (this);

			//Split if needed
			if (elements.Count > elementCapacity) {

				Split ();

				//Distribute elements to corespond child node
				List<IQuadtreeAgent>.Enumerator er = elements.GetEnumerator();
				while (er.MoveNext ()) {
				
					if (boundary.ContainPoint2D (er.Current.GetCenter ()) != CollisionResult.None) {
					
						if (!Add (er.Current)) {
							#if DEBUG
							Debug.LogWarning("Distribute element to child node fail, elemnt is out of node boundary." +
								"We need to add from root");
							#endif

							//add element from root if can't add to child node
							rootQuadtree ().Add (er.Current);
						}

					} else {

						rootQuadtree ().Add (er.Current);
					}
						
				}

				//clear elements
				elements.Clear();
			}

			return true;
		}
Example #8
0
		/**
		 * Add new element to quadtree at next frame
		 * This will start from root quadtree node
		 **/
		public void AddNextFrame(IQuadtreeAgent newElement){

			elementsNextFrame.Add (newElement);
		}