Click here to Skip to main content
Click here to Skip to main content

A Simple QuadTree Implementation in C#

By , 29 Oct 2008
 
Items in a QuadTree with nodes in random colours

User Selects a region and the QuadTree selects items

The Selected items

Introduction

A QuadTree is a spatial partitioning strategy used to make queries on relationships between 2D spatial data such as coordinates in a Geographic Information System (GIS), or the location of objects in a video game. For instance, you may need to know all of the objects within a region on a map, test whether objects are visible by a camera, or optimize a collision detection algorithm.

The QuadTree is so named because it recursively partitions regions into four parts, with leaf nodes containing references to the spatial objects. Querying the QuadTree is a function of traversing the tree nodes that intersect the query area.

The OctTree is the analogous structure used for 3 dimensional problems. 

For a masterful collection of demos and variations on the QuadTree and other spatial indexing methods, see Frantisek Brabec and Hanan Samet's site, or use the references at the end of this article.

Background

There are many spatial partitioning methods, each with the goal of providing an efficient way of determining the position of an item in a spatial domain. For example, a database query can be considered as a graphical problem. Consider a query on a database containing date of birth and income: a query against all people between 35 and 50 years of age and incomes between 30,000 and 60,000 per year is the same as a query for all restaurants in the city of Vancouver: they are 2 dimensional spatial queries.

Several spatial indexing methods are more efficient in time and space, and are easily generalizable to higher dimensions. However, the QuadTree is specialized to the 2D domain, and it is easy to implement.

Algorithm

The general strategy of the QuadTree is to build a tree structure that partitions a region recursively into four parts, or Quads. Each Quad can further partition itself as necessary. A pre-requisite is that you must know the bounds of the area to be encompassed; the basic algorithm does not lend itself to the addition or removal of areas under consideration without rebuilding the index.

Insertion

When an item is inserted into the tree, it is inserted into a Quad that encompasses the item's position (or spatial index). Each Quad has a maximum capacity. When that capacity is exceeded, the Quad splits into four sub-quads that become child nodes of the parent Quad, and the items are redistributed into the new leaves of the QuadTree. Some variations set the maximum capacity to one, and subdivide until each leaf contains at most a single item (Adaptive QuadTree).

Querying

To query a QuadTree for items that are inside a particular rectangle, the tree is traversed. Each Quad is tested for intersection with the query area.

  1. Quads that do not intersect are not traversed, allowing large regions of the spatial index to be rejected rapidly.

    Case 1: Querying QuadTree

  2. Quads that are wholly contained by the query region have their sub-trees added to the result set without further spatial tests: this allows large regions to be covered without further expensive operations.

    Case 2: Querying QuadTree

  3. Quads that intersect are traversed, with each sub-Quad tested for intersection recursively.

    Case 3: Querying QuadTree

  4. When a Quad is found with no sub-Quads, its contents are individually tested for intersection with the query rectangle.

Other Operations

Other operations on the QuadTree could include:

  1. Deletion: An object is removed from the QuadTree, empty quads are removed
  2. Merge: Two quadtrees are merged, indexes are rebuilt
  3. Nearest Neighbour: Common to more advanced spatial indexes, a Query could ask for the nearest neighbours to a given object. A simple implementation would be to take the object's bounding rect and inflate it by an amount based on the neighbor proximity. Objects in the result set would be sorted by increasing distance.

These operations are not demonstrated in this code.

Variation

This implementation of the QuadTree has the following variations:

The QuadTree has been changed to index items with rectangular bounds rather than points. This allows it to be used with lines, and polygons.

  • On insertion, new quads are created until there are no Quads able to contain an item's rectangle. IE: the item is inserted into the smallest quad that will contain it.
  • There is no maximum number of items in a Quad, there is a minimum Quad size (necessary to avoid massive tree growth if an item happens to have a very small area).
  • Because the Quad an item is stored in is related to the size of the item, both leaf nodes and parent nodes store items.
  • The QuadTree's performance will be severely impacted if there are many large items.
  • The Quadtree's performance will be best when the size of most items are close to the minimum quad size.

After writing this code, I find that this particular variation bears a striking resemblance to the "MX-CIF QuadTree".

Note: There are other operations on QuadTrees such as deleting a node, or find the nearest neighbour. These are not supported in this implementation.

The following two diagrams show the spatial relationship of the QuadTree with the tree structure. The coloured regions represent objects in the spatial domain. Those that are entirely within a quad are shown in the tree structure in their smallest enclosing quad. You can see that the green shape, since it intersects two of the highest level Quads and does not fit into either is placed in the root quad. The red and purple shapes are placed in child nodes at level one since they are the largest enclosing Quads. The blue shape is at level three along with the orange shape. The Yellow shape is at level four. This tree is adaptive in that it does not create quads until insertion is requested.

Spatial drawing of shapes in a QuadTree

Tree representation of QuadTree

Using the Code

The QuadTree class is a generic class. The generic parameter has a restriction that it must inherit from the IHasRect interface which defines a property Rectangle. Creating a QuadTree requires an area, the demo application uses the main form's ClientRectangle.

QuadTree<Item> m_quadTree = new QuadTree<Item>(this.ClientRectangle); 

Inserting items into the QuadTree is done on a left mouse click, querying items in a QuadTree is done with a right mouse drag:

private void MainForm_MouseUp(object sender, MouseEventArgs e) 
{ 
    if (m_dragging && e.Button== MouseButtons.Right) 
    { 
        m_selectedItems = m_quadTree.Query(m_selectionRect);
        m_dragging = false;    
    } 
    else 
    { 
        Random rand = new Random(DateTime.Now.Millisecond); 
        m_quadTree.Add(new Item(e.Location, rand.Next(25) + 4)); } Invalidate(); 
    }
}

Run the demo application, and left click anywhere in the client rectangle: an object is inserted at the click point with a random size. Right-click and drag: a selection rectangle is created. Release the mouse button: the QuadTree is queried with the selection rectangle. The QuadTree renderer draws the QuadTree nodes and the objects in the QuadTree in random colours. It also draws the selection region and highlights the selected nodes.

Performance

There are two components of QuadTree performance: insertion and query. Insertion can be very expensive because it involves several intersection tests per item to be inserted. The number of tests depends on the size of the region (the root of the QuadTree) and on the minimum Quad size configured. These two numbers have to be tuned per application. Loading many items into the QuadTree (bulk load, or indexing) tends to be very CPU intensive. This overhead may not be acceptable; consider storing the QuadTree structure on disk (not covered in this article).

The QuadTree is designed to be faster at querying the spatial domain than iteration, but the performance of the index depends on the distribution of objects in the domain. If items are clustered together, the tree tends to have many items in one branch which defeats the strategy of being able to cull large regions, and reduce the number of intersection tests. The worst case performance happens when all objects are in one small cluster that is the same size as the smallest Quad; in this case the performance of the QuadTree will be slightly worse than just iterating through all objects.

If items are uniformly distributed across the spatial domain, performance is approximately O(n*log n).

Points of Interest

  • Generic implementation; allows you to use it with any class that implements IHasRect interface.
  • Colour used to draw the node is stored in an hashtable; allows the colour of the Quad on screen to be constant over the life of the QuadTree.
  • In the QuadTreeRenderer class, note the anonymous delegate used to draw the QuadTreeNodes; allows the QuadTree to be tested, and visualized, without adding specific code to the class to do so.

References

  • H. Samet, The Design and Analysis of Spatial Data Structures, Addison-Wesley, Reading, MA, 1990. ISBN 0-201-50255-0
  • H. Samet, Applications of Spatial Data Structures: Computer Graphics, Image Processing, and GIS, Addison-Wesley, Reading, MA, 1990. ISBN 0-201-50300-0.
  • Mark de Berg, Marc van Kreveld, Mark Overmars, Otfried Schwarzkopf, Computational Geometry: Algorithms and Applications, 2nd Edition, Springer-Verlag 2000 ISBN: 3-540-65620-0

History

  • Initial version with regions and simple Insert and Query operations, demo application

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Michael Coyle
Architect Blue Toque Software
Canada Canada
Member
I've been lead architect in several software companies. I've worked in the Justice and Public Safety area for the last 7 years, writing facial recognition, arrest and booking software and emergency management/GIS software. Prior to that I worked in the games industry with 3D animation.
 
Currently I'm working on some GIS/mapping software for outdoor enthusiasts. I intend to spin off portions of this into the open source community as time permits.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionPoint variant?memberThomas Schmidt2 Apr '12 - 21:15 
Michael,
thank you for your great article!
Do you also have the 'point' variant of the tree? I just need to locate POIs so I don't need the overhead.
Thomas
AnswerRe: Point variant?memberMichael Coyle4 Apr '12 - 11:12 
I've placed the code in a bitbucket repo[^] and added a new class (PointQuadTree) that works on points. Let me know if it meets your needs. If you're interested you can always modify the code yourself and contribute it back to the repo.
GeneralRe: Point variant?memberThomas Schmidt4 Apr '12 - 11:20 
Hey you're quick!
Thanks a lot. I'll have a look.
GeneralRe: Point variant?memberMichael Coyle4 Apr '12 - 11:21 
Oh, and I forgot to add I have NOT tested the new classes at all!
QuestionHow could I use this with geocoordinates?memberClinton Sanchez29 Feb '12 - 19:09 
I want to create an in-memory spatial index for geo-coordinate data. Any ideas on what it'd take to repurpose this for geographic data instead of geometric? I'm mainly concern with "standard" 4326 projection
AnswerRe: How could I use this with geocoordinates?memberMichael Coyle1 Mar '12 - 10:47 
First off, 4326 is not a projection, it's coordinates in the "unprojected" geographic coordinate system.
 
I would refer you to the article: Why EPSG 4326 is usually the wrong coordinate system[^] In this article he talks about how straight lines in the on-screen rendering of 4326 are curved lines in the real world, and vice versa. These are known as Great Circle[^] routes.
 
Note that even drawing the "unprojected" coordinates on screen, you most likely "projecting" them into the Plate Caree projection without even knowing it because it's impossible to draw a curved object on a flat surface without implicit projection.
 
4326 is a spherical coordinate system. The QuadTree would work for this system in an approximate sense as long as the quads were small, and not too far toward the poles; things would become less accurate the further north or south of 60 degrees you go. So for example if the area you are interested in is on the scale of a city (50km), and in the United States, you could probably use the QuadTree with reasonable success without modification.
 
I am currently using this very same QuadTree in a GIS I've written; however, the coordinates are projected into EPSG:3785 which is the one that Google Maps, and Bing Maps use to represent the world on screen. In this projection, the coordinates are rectangular X and Y and the accuracy of the QuadTree is as good as you will need outside of an actual GIS. There are still scale and other issues where a query against the structure will return items that, while "inside" the quad with respect to the projected coordinates, are "outside" with respect to the real world.
However, since you're drawing projected coordinates on screen, this does not turn out the be an issue. Unless you need the accuracy this QuadTree will do.
 
If you need something really accurate, use SQL Spatial extensions or one of the open source projection libraries like Proj.NET
Michael Coyle
TrueNorth Geospatial
www.TrueNorthGeospatial.com

GeneralMy vote of 5membermanoj kumar choubey19 Feb '12 - 21:36 
Nice
QuestionGreat articlememberHarvey Green25 Sep '11 - 20:45 
Thanks for this article; its invaluable when searching some 2D data in a lookup table quickly.
Note that the bug that is mentioned in the below comments is still present in the code - its related to the "IsEmpty" property. See the comment titled "I found a bug".
Questionthanks michaelmemberKiraya8 Sep '11 - 22:21 
Thanks very much for this interesting article.
very clear and smart work.
 
cheers from italy.
SuggestionThank you for this great contributionmemberGeorge Mamaladze10 Jul '11 - 9:47 
First of all thank you for this great article and code.
I have reused it in my project with minor modifications.
 
http://sourcecodecloud.codeplex.com/[^]
 
So I'd like to share my experience with you and community:
One of my goals was to quick test an area weather it has some intersections or not.
 
public bool HasContent(RectangleF queryArea) {...}
 
I could use the Query method and check the list returned for number of elements to be 0.
However the better way would be to perform the similar tree iteration like in Query method and break it up as soon as first intersection where found.
 
The second thing is that I switched to LinkedList everywhere instesd of List, thus I have seen that only operations used on them where Add and enumeration. It could increase performance and save the memory.
 
Best regards
George Mamaladze
GeneralRe: Thank you for this great contributionmemberMichael Coyle10 Jul '11 - 10:21 
Thanks for the kind words George.
 
I can see how the "HasContent" call would be quicker for intersection testing, that's a great optimization.
 
I also agree with the LinkedList substitution -- it should make for faster comparison. It would probably be even faster for testing with an array, but slower on the insert.
GeneralRe: Thank you for this great contributionmemberGeorge Mamaladze11 Jul '11 - 11:49 
Word Cloud (Tag Cloud) Generator Control for .NET Windows.Forms in c#[^]
 
I have included your name and the reference in the credits section at the end of my article.
GeneralFile-based solutionmemberwalterman13 Oct '10 - 11:38 
Great article, thanks for posting. Any thoughts on how this could be modified so the contents and nodes can be stored & searched from a file? I have some data that needs to be stored in a QuadTree like structure, but is much too big for RAM. I'm looking for some brilliant ideas...
 
Walter
AnswerRe: File-based solution [modified]memberMichael Coyle13 Oct '10 - 12:19 
I have also been thinking about this.
 
I imagine that you've already thought about the performance balance between indexing (calculating the QuadTree) on the fly versus the storage requirements (space) and load times. I have found that the time taken to load spatial data far exceeds the time taken to project (in the case of geospatial data) and index. My decision was to cache the projected coordinates, but still index the file on the fly.
 
However, here's an idea, though unimplemented.
 
Each quad has a number; 0,1,2,3 for the top level. Subsequent levels also have numbers from 0 to 3. Each level can thus be "addressed" by a bitfield, or binary number as so:
 
1.0: 0000
1.1: 0001
1.2: 0010
1.3: 0011
 
2.0: 0100
2.1: 0101
2.2: 0110
2.3: 0111
 
3.0: 1000
3.1: 1001
3.2: 1010
3.3: 1011
 
4.0: 1100
4.1: 1101
4.2: 1110
4.3: 1111
 
1111 1111 1111 1111 1111 1111 1111 1111
This can be extended to the depth of the QuadTree. In this way an int can contain the address of 16 levels or 16^4 quads, which should be enough. If you need more you can move to a long integer, if you need less, move to a short integer.
 
Using a binary file, you write out the "address" of the quad, followed by the number of elements in the quad, followed by each element. If the element is in fact stored elsewhere, you write out the ID of each element.
 
The task of reading in the file becomes mostly decoding each Quad's "address", and "resolving" the ID of each element as it is read from the file and inserting it (without spatial tests) into the quad.
 
Note that if your elements can be moved, you would still have to test on insert which would make storing the QuadTree in this form pretty much useless as you would have to re-index everything each tie it is loaded.
 
How does this sound?
 
PS: Another way to store this is to store the QuadTree node address as an int with each element you store. In a database this could be as simple as an integer column stored with every element. As you read the elements you would be able to place it in the correct quad quite easily.

modified on Wednesday, October 13, 2010 8:41 PM

GeneralMy vote of 2memberchengiz526 Aug '10 - 5:40 
Simple is right
GeneralAccess C# dll from vb.netmemberralstogj9 Sep '09 - 11:10 
Hi
 
I am updating some 20 year old code in Autocad lisp that takes rectangles that
surround text items and searches for text rectangles that overlap and filters out text based on a third elevation criteria.
 
The raw data comes from scans of the sea floor and there can be 1000's of text rectangles. The existing rountine is just a loop that takes hours to run for large datasets.
 
I am trying to use your Quadtree .dll from vb.net to speed up the code.
 

Accessing the C# dll code from vb.net is something I have never done before I have referenced the .dll ok and come up with the following to load rectangles into the tree and query it. But do not know how to define a rectangle object correctly or define the item as an IHasRect correctly for the quadtree definition from vb.net. If you could provide an example of how you would do it that would be greatly appreciated
 
Regards
 

Justin Ralston
 

 
Public Sub Find_Overlapping_Text()
 
'Create the quadtree using the C# .dll from the website http://www.codeproject.com/KB/recipes/QuadTree.aspx33
'to the extents of the points text
 
'To access the C# code that you want it be compiled as a DLL. Once that is done,
'simple add a reference to that project to your VB.Net project, import the namespace you need,
'and then you can use the C# code
 
Dim r As Rectangle = (100),100,100,100) 'Me.ClientRectangle
Dim item As IHasRect
 
Dim m_quadTree As New QuadTree(Of Item)(r)
'Dim m_quadTree As New QuadTree(Of Item)(Me.ClientRectangle)
 
'add random points (text rectangles) into the quadtree for querying
 
Random(rand = New Random(DateTime.Now.Millisecond))
m_quadTree.Add(New Item(e.Location, rand.Next(25) + 4))
 

'loop through all the text rectangles and
'Query the quadtree with a rectangle to find any other text objects under it
Dim m_selectionRect As Rectangle = (20),20,20,20)
m_selectedItems = m_quadTree.Query(m_selectionRect)
 
End Sub
GeneralRe: Access C# dll from vb.netmemberMichael Coyle9 Sep '09 - 12:50 
Understand I'm not an expert VB programmer.
There should be no trouble with referencing a c# assembly from VB, the only problems you may encounter are if I used some methods from a different version of the .NET framework. Other than this, all .NET assemblies should be interoperable.
 
To implement the IHasRect interface in VB you would use the following syntax:

Public Class Item
Implements IHasRect
 
Dim m_rect as RectangleF
Public Property Rectangle() As RectangleF
Get
Return x
End Get
Set(ByVal Value As Integer)
x = value
End Set
End Property
 
End Class
 

Then, in your code, replace the line "Dim item As IHasRect" with Dim item As Item,
and in your loop create new Item objects and assign them rectangle values.
 
Let me know how this goes.
GeneralRe: Access C# dll from vb.netmemberralstogj9 Sep '09 - 12:59 
Thanks Micheal
 
I will give it a go tonight and let you know now things go.
 
Justin
GeneralRe: Access C# dll from vb.netmemberralstogj10 Sep '09 - 0:18 
Hi
 
Have had a go but am getting the following errors. Not sure what to do as this is at the limits of my current knowledge
of vb.net
I have explain wants happening below with screen captures showing the errors in vb.net editor
 
http://screencast.com/t/p1RRmDpr[^]
 
http://screencast.com/t/NTpWfAakYU[^]
 
http://screencast.com/t/p00DT4k8WZ[^]
 

Regards
 

Justin Ralston
GeneralRe: Access C# dll from vb.netmemberMichael Coyle10 Sep '09 - 6:59 
Justin: so sorry for the incorrect code I posted yesterday; like I said I am not a VB programmer, but I fired up Visual Studio and this class compiles
 
The key is "Public ReadOnly Property Rectangle() As RectangleF Implements IHasRect.Rectangle"
 
Imports QuadTreeLib
Imports System.Drawing
 
Public Class Item
Implements IHasRect
 
Dim m_rect As RectangleF
 
Public ReadOnly Property Rectangle() As RectangleF Implements IHasRect.Rectangle
Get
Return m_rect
End Get
End Property
 
End Class
 
For your second problem, you call QuadTree.Insert to add items to the QuadTree.
For the last question, you query the QuadTree using a rectangle and it returns all items that are in that rectangle.
The query returns a generic list if Item class.
GeneralRe: Access C# dll from vb.netmemberralstogj14 Sep '09 - 0:12 
Micheal
 
Thanks for your last bit of code I now have the the tree creating. But am having trouble inserting objects I have looked at your C# code for the item.cs class and translated to vb.net as follows :-
 
Imports System.Text
Imports QuadTreeLib
Imports System.Drawing
 
'To access the C# code that you want it be compiled as a DLL. Once that is done,
'simple add a reference to that project to your VB.Net project, import the namespace you need,
'and then you can use the C# code
 
Public Class Item
Implements IHasRect
 
Dim m_rect As RectangleF
 
Public ReadOnly Property Rectangle() As RectangleF Implements IHasRect.Rectangle
Get
Return m_rect
End Get
End Property
 

Public Sub New(ByVal P As Point, ByVal Size As Integer)
Dim m_size As Integer
Dim m_rectangle As RectangleF
 
m_size = Size
m_rectangle = New RectangleF(P.X, P.Y, m_size, m_size)
 
End Sub
 

End Class
 

and have the following sub rountine to create the tree and try and insert and qurey objects:-
 
Public Class Textlap
<Autodesk.AutoCAD.Runtime.CommandMethod("TL")> _
Public Sub Find_Overlapping_Text()
 
'Create the quadtree using the C# .dll from the website http://www.codeproject.com/KB/recipes/QuadTree.aspx
'to the extents of the points text
 
'To access the C# code that you want it be compiled as a DLL. Once that is done,
'simple add a reference to that project to your VB.Net project, import the namespace you need,
'and then you can use the C# code
 
Dim r As New Rectangle(100, 100, 100, 100) 'Me.ClientRectangle
' Rectangle(x upper lefthand corner ,y upper lefthand corner,width,height)
 
Dim m_quadTree As New QuadTree(Of Item)(r)
'Dim m_quadTree As New QuadTree(Of Item)(Me.ClientRectangle)
 
'add random points (text rectangles) into the quadtree for querying
'integer
 
'Random(rand = New Random(DateTime.Now.Millisecond))
'm_quadTree.Insert(new Item(e.Location, rand.Next(25) + 4));
Dim aa As Point
 
aa.X = 160
aa.Y = 85
 
'Dim jj As New Item(aa, 5)
 
m_quadTree.Insert(New Item(aa, 5))
 
'loop through all the text rectangles and
'Query the quadtree with a rectangle to find any other text objects under it
Dim m_selectionRect As New Rectangle(150, 90, 20, 20) 'query rectangle
Dim m_selectedItems As List(Of Item)
m_selectedItems = m_quadTree.Query(m_selectionRect)
 
End Sub
 
End Class
 
The code runs and gets pass the m_quadtree.insert line but when I look at the m_quadtree as a watch the tree item count is still zero. I guess the New constructor in vb is not what I have to use can you suggest what I should try.
 

Regards
 

Justin Ralston
GeneralRe: Access C# dll from vb.netmemberMichael Coyle14 Sep '09 - 18:34 
When you create the QuadTree you give it a rectangle starting at 100,100 and a width and height of 100. The QuadTree is bounded by 100,100 on the top left, and 200,200 at the bottom right.
 
2 problems:
 
1) The item you add to the QuadTree is at 160,85 and is 5x5: this is outside the bounds of your QuadTree. It is never inserted. On line 152 of QuadTreeNode there is a trace warning that should appear on the debug output when you run it. I should probably have thrown an exception at that point.
 
2) the query includes an area that is outside the bounds of the QuadTree. This isn't really a problem as the code should be able to handle it, but it's not a case I explicitly tested.
 
Make your QuadTree start at 0,0 and of size 200,200 and it should work.
GeneralRe: Access C# dll from vb.netmemberralstogj16 Sep '09 - 0:17 
Sniff | :^)
 
Oops I was visualising the box going down as the Rectangle method said the x was for the upper left corner in the vb IDE
 
I have changed the code as you suggested and it runs no problem.
 
I have started putting it together with the autocad code and objects.
 
At the moment the quadtree takes integers could it be upgraded to take Doubles floating points?
 
or would it be best to times everything by say 100 to scale it up to give me more accuracy and upgrade the code to take longs?
 
Its just the raw point data I often have of the sea floor can be spread over a responible area of say 1 km by 1 km. I guess i could break the area down into a grid of 32,767 units /100 squares the maximum storage value of an integer.

 
Regards
 
Justin Ralston
Questionremove node function?memberMember 17427019 Aug '09 - 13:22 
Hi,
 
Anybody know, how implement remove node function?
 
Thanks!
AnswerRe: remove node function?memberMichael Coyle10 Aug '09 - 9:36 
Good question. I obviously wrote this to fulfill a need I had to make a read-only structure.
 
The current QuadTree only contains methods that pertain to the spatial nature of the data.
In order to remove nodes you will need to extend it to contain some other attribute(s) and
method(s) to select the node using whatever criteria you may decide to identify your data.
 
Three steps:
 
1) Fnd the node you need to remove.
You pretty much need a reference to a node at some point to remove it from the structure.
This example can only be queried spatially (ie: using an extents, or rectangle). The
spatial query returns a list of nodes in that area.
 
You would need to add another query to get a node using attributes you may add to a node
weather that's a unique ID or some other way to select the node.
 
In my private implementation of the Quadtree I wrote a "nodeTest" delegate that is passed in
with a rectangular structure. The delegate is called for each item that matches the spatial
query and returns "True" when a node is to be selected. This would allow you to select nodes
with a given name or ID.
 
2) Extend the QuadTree to remove nodes.
The remove method takes a node or node ID as a paramter and would recurse through the tree
looking for the node in the Contents of every node. You could use Contents.Contains(...)

When found just use Contents.Remove(node);
 
Note that because of the structure of this particular implementation, I have factored out
the contents of a node from the implementation of the "Quads". It really is as
simple as removing the node from the Contents list.
 
3) profit!
 
Obviously this will require some work on your part, but working through this will also help you understand the data structure better.
 
I hope this is clear.
GeneralRe: remove node function?memberMember 174270110 Aug '09 - 11:54 
Understand, I am translated your algorithm to C++ and added ID value to each rectangle for find quadnode function and remove quadnode from quadtree, if contents is empty and quadnode has not filled quadnode childs. May be correctly when quadnode childs need reinsert, but require high performance. Need try...
 
Thanks!
GeneralRe: remove node function?memberMichael Coyle4 Apr '12 - 11:28 
I;ve been re-indexing the QuadTree when I add or remove items.
GeneralThe circle is not placed exactly under the mouse clicking location.memberdanielmark9 Mar '09 - 5:31 
Hello,
 
I just found that the placed circle is not exactly under the mouse click location.
 
Thank you
GeneralRe: The circle is not placed exactly under the mouse clicking location.memberMichael Coyle9 Mar '09 - 6:33 
It's quite possible there's an error and I'm not accounting for an offset from the mouse click position to the control in question.
 
However, the point of the application is that the circles are "placed" into the quad-tree, and are then "selected" using the algorithm. Any error in placing the circles shouldn't affect the QuadTree algorithm which involves the sorting of the circles into the nodes or leaves, and dividing the hit-test or selection test into just certain nodes.
 
I've been using this implementation to very good effect in a mapping application and so far it's proven to be stable.
GeneralRe: The circle is not placed exactly under the mouse clicking location.memberdanielmark9 Mar '09 - 16:09 
Thank you
GeneralRe: The circle is not placed exactly under the mouse clicking location.memberDukeForge1 May '09 - 17:29 
The circle is created correctly. Where you click is used as the the upper-left corner of a rectangle in which a circle is placed.
GeneralFound a bugmemberrlukashuk15 Dec '08 - 12:46 
I found a bug relating to the MinArea in QuadTreeNode.IsEmpty
 
The following code:
 

public bool IsEmpty {  get  { return m_bounds.IsEmpty || m_nodes.Count == 0; } }
 
Should be:
 
public bool IsEmpty {  get  { return m_bounds.IsEmpty || (m_nodes.Count == 0 && m_contents.Count == 0); } }

GeneralRe: Found a bugmemberMichael Coyle15 Dec '08 - 12:51 
Thanks for that; I'll update the code at some point.
GeneralSource Code LinksmemberHenry Minute29 Oct '08 - 23:49 
This is a very interesting article.
Unfortunately the links to the demo and source appear to be broken.
Please fix them as I would like to have a look at the code.
 
Henry Minute
 
If you open a can of worms, any viable solution *MUST* involve a larger can.

GeneralSource Code LinksmemberHenry Minute29 Oct '08 - 23:49 
This is a very interesting article.
Unfortunately the links to the gemo and source appear to be broken.
Please fix them as I would like to have a look at the code.
 
Henry Minute
 
If you open a can of worms, any viable solution *MUST* involve a larger can.

GeneralRe: Source Code LinksmemberMichael Coyle30 Oct '08 - 7:56 
Sorry; links fixed now.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 30 Oct 2008
Article Copyright 2008 by Michael Coyle
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid