internal bool Add(QTPoint pt, N range, D data) { // this.HalfRange = (dynamic) range * 0.5; if (Point == null && Children == null) //TODO: is Children == null check neccisary? { // first time setting Point = pt; Range = range; Data = data; ++QuadTree <N, D> .QTNodeCount; return(true); } else if (Point.Equals(pt)) // TODO: anything about range? { // TODO: what about if this isnt a leaf and the point matches? Data = data; return(false); } else // a leaf node or a parent node { int quad = GetQuadrant(pt); if (Children == null) { Children = new QTNode <N, D> [4]; } if (Children[quad] == null) { Children[quad] = new QTNode <N, D>(); } return(Children[quad].Add(pt, range, data)); } }
/// <summary> <returns> /// True if the given point is inside the current node bounds, otherwise false. /// </returns> </summary> /// <param name="pt"></param> internal bool Contains(QTPoint pt) { return((dynamic)pt.X >= Point.X && (dynamic)pt.X <= (dynamic)Point.X + Range && (dynamic)pt.Y >= Point.Y && (dynamic)pt.Y <= (dynamic)Point.Y + Range); }
/// <summary> /// Returns a point and range that captures all areas contained by both points and ranges /// </summary> /// <typeparam name="N"></typeparam> /// <param name="point1"></param> /// <param name="range1"></param> /// <param name="point2"></param> /// <param name="range2"></param> /// <param name="ExistingPointToChange"></param> /// <param name="ExistingRangeToChange"></param> public static void Capture(QTPoint point1, dynamic range1, QTPoint point2, dynamic range2, ref QTPoint ExistingPointToChange, ref dynamic ExistingRangeToChange) { // Get the minimum X and Y's ExistingPointToChange.X = point1.X < point2.X ? point1.X : point2.X; ExistingPointToChange.Y = point1.Y < point2.Y ? point1.Y : point2.Y; // Get the maximum X and Y's dynamic x = (point1.X + range1 > point2.X + range2 ? point1.X + range1 : point2.X + range2) - ExistingPointToChange.X; dynamic y = (point1.Y + range1 > point2.Y + range2 ? point1.Y + range1 : point2.Y + range2) - ExistingPointToChange.Y; ExistingRangeToChange = x; }
/// <summary> /// Tests if the given point range bounds overlap this current node bounds. /// </summary> /// <param name="pt"></param> /// <param name="otherRange"></param> /// <returns>True if they overlap, otherwise false.</returns> internal bool Overlaps(QTPoint pt, N otherRange) { // is min.rightmost > max.leftmost? bool XOverlap = (dynamic)Point.X <= pt.X ? (dynamic)Point.X + Range > pt.X : (dynamic)pt.X + otherRange > Point.X; // is min.topmost > max.botommost? bool YOverlap = (dynamic)Point.Y <= pt.Y ? (dynamic)Point.Y + Range > pt.Y : (dynamic)pt.Y + otherRange > Point.Y; // if both are true, then the two squares overlap return(XOverlap && YOverlap); }
public Image Draw(QTPoint pt, N range, Color[] DataColor) { Image img = new Bitmap((int)Math.Ceiling((dynamic)range), (int)Math.Ceiling((dynamic)range)); Graphics drawing = Graphics.FromImage(img); //paint the background drawing.Clear(Color.Black); if (RootNode != null) { RootNode.Draw(pt, range, ref drawing, ref DataColor); } drawing.DrawImage(img, 0, 0); drawing.Save(); drawing.Dispose(); return(img); }
internal void Draw(QTPoint pt, N range, ref Graphics drawing, ref Color[] dataColor) { if (pt != null && Data != null) { // x y is upper left... drawing.FillRectangle(new System.Drawing.SolidBrush(dataColor[(dynamic)Data]), (float)Point.X, (float)((dynamic)Point.Y), (float)(dynamic)Range, (float)(dynamic)Range); } if (Children != null) { for (int i = 0; i < Children.Length; ++i) { if (Children[i] != null) { Children[i].Draw(pt, range, ref drawing, ref dataColor); } } } }
/// <summary> /// Adds a point data range to the data structure. /// </summary> /// <param name="data">The data to add</param> /// <param name="pt">The botom left corner for the point to add</param> /// <param name="range">The optimal size of the box</param> /// <returns>True if a new point was added, false if it was a replacement or failure to add.</returns> public bool Add(QTPoint pt, N range, D data) { if (RootNode == null) { RootNode = new QTNode <N, D>(); return(RootNode.Add(pt, range, data)); } // If the point to add is in the current bounds, then add it. if (RootNode.Contains(pt)) // TODO: do i need to check if it overlaps as well or something? { return(RootNode.Add(pt, range, data)); } else { // The point is out of the current bounds, we need to move the root down a level. // Get the range and the point for the new root node QTPoint NewRootPt = new QTPoint(); dynamic NewRootRange = 0; QTPoint.Capture(RootNode.Point, RootNode.Range, pt, range, ref NewRootPt, ref NewRootRange); // Add the current root to the new node QTNode <N, D> NewRoot = new QTNode <N, D>(); if (!NewRoot.Add(pt, range, data)) { throw new Exception("How did we get here? I thought we were adding to an empty node?"); } bool worked = NewRoot.Append(RootNode); // Update out root node // TODO: can optimize some lines out once we pass testing if (worked) { RootNode = NewRoot; return(true); } else { throw new Exception("Why did that not work?"); } } }
internal bool Query <C>(QTPoint pt, N range, ref C found) where C : System.Collections.ICollection { dynamic obj = found; if (this.Overlaps(pt, range)) // is this working? { obj.Add(Data); if (Children != null) { for (int i = 0; i < 4; ++i) { if (Children[i] != null) { Children[i].Query(pt, range, ref found); } } } return(true); } return(false); }
/// <summary> /// Gets the data values in the given point range and puts them into the found object. /// </summary> /// <param name="pt">The bottom left point to start the search from</param> /// <param name="range">the size of the range tosearch for</param> /// <param name="found">TODO: Some sort of collection to add the found data to.</param> /// <returns>True if any found, false otherwise.</returns> public bool Query <C>(QTPoint pt, N range, ref C found) where C : System.Collections.ICollection { return(RootNode != null?RootNode.Query(pt, range, ref found) : false); }
public bool Find(QTPoint pt) { return(RootNode != null?RootNode.Find(pt) : false); }
/// <summary> /// ╔═════════╦══════════╗ /// ║ 3 ║ 2 ║ /// ║ TopLeft ║ TopRight ║ /// ╠═════════╬══════════╣ /// ║ 0 ║ 1 ║ /// ║ BotLeft ║ BotRight ║ /// ╚═════════╩══════════╝ /// </summary> /// <param name="pt"></param> /// <returns></returns> internal int GetQuadrant(QTPoint pt) { // TODO: is / 2.0 or * 0.5 faster? Inital testing says they are about the same. return((pt.X - Point.X > (dynamic)Range * 0.5 ? 1 : 0) // left or right + (pt.Y - Point.Y > (dynamic)Range * 0.5 ? 2 : 0)); // top or bottom }
internal bool Find(QTPoint pt) { throw new NotImplementedException(); }