Dart DocumentationcollisionsQuadTreeXYAabb

QuadTreeXYAabb class

/// see /// * Quadtree at wikipedia /// * JavaScript QuadTree Implementation /// * Quick Tip: Use Quadtrees to Detect Likely Collisions in 2D Space see Quadtree at wikipedia JavaScript QuadTree Implementation * Quick Tip: Use Quadtrees to Detect Likely Collisions in 2D Space TODO add testcase

class QuadTreeXYAabb{
 /// (x, y, width, height) bounds of the QuadTree
 final _dim = new Aabb3();
 final _splitPoint = new Vector3.zero();

 /// Whether the QuadTree will contain points (true), or items with bounds (width / height)(false).
 final int maxDepth;
 /// The maximum number of children that a node can contain before it is split into sub-nodes.
 final int maxChildren;

 //interleave data [AAbb3, obj, AAbb3, obj, ....]
 final _children = new List();
 //TODO optimize to reuse nodes (recycle, pool)
 final _nodes = new List<QuadTreeXYAabb>(4);
 var _isLeaf = true;

 QuadTreeXYAabb(x, y, w, h, [this.maxDepth = 4, int maxChildren = 4]): this.maxChildren = maxChildren << 1 {
   _dim.min.setValues(x, y, 0.0);
   _dim.max.setValues(x + w, y + h, 0.0);
   _splitPoint.setFrom(_dim.min).add(_dim.max).scale(0.5);
 }

 get isLeaf => _isLeaf;
 get nbItems => (_children.length >> 1) + ((_isLeaf)? 0 : (_nodes[0].nbItems + _nodes[1].nbItems + _nodes[2].nbItems + _nodes[3].nbItems));
 get nbItemsL0 => _children.length >> 1;

 /// use [reset] to reset the instance instead of create a new one with same bounds.
 reset() {
   _children.clear();
   _isLeaf = true;
 }

 bool insert(Aabb3 v, obj) {
   var r = findRegion(v);
   if (r != null) {
     r._insert(v, obj);
//      if (this.maxDepth == 10) {
//        obj.ps.color[obj.i] = (r.maxDepth == 10)? 0x0000ffff : 0x00ff00ff;
//      }
   }
   return (r != null);
 }

 QuadTreeXYAabb findRegion(Aabb3 v) {
   if (v.min.x < _dim.min.x || v.max.x > _dim.max.x || (v.min.y < _dim.min.y) || v.max.y > _dim.max.y) {
     return null;
   }
   return _findRegion(v);
 }

 _findRegion(Aabb3 v) {
   var r = null;
   if (!_isLeaf) {
     var n = (v.min.y <= _splitPoint.y)?  0 : 2;
     n = (v.min.x <= _splitPoint.x)?  n : n + 1;
     r = _nodes[n].findRegion(v);
   }
   return (r == null) ? this : r;
 }

 _insert(Aabb3 v, obj) {
   if (_isLeaf && maxDepth > 0 && _children.length >= maxChildren) {
     _split();
     var data = new List.from(_children, growable: false); // TODO use a static arrays
     _children.clear();
     for (var i = 0; i < data.length; i +=2) {
       insert(data[i], data[i+1]);
     }
     insert(v, obj);
   } else {
     _children.add(v);
     _children.add(obj);
   }
 }

 _split() {
   if(_nodes[0] == null) {
     var x = _dim.min.x;
     var y = _dim.min.y;
     var w2 = _splitPoint.x - _dim.min.x;
     var h2 = _splitPoint.y - _dim.min.y;
     var m = maxChildren >> 1;
     var d = maxDepth - 1;
     _nodes[0] = new QuadTreeXYAabb(x     , y     , w2, h2, d, m);
     _nodes[1] = new QuadTreeXYAabb(x + w2, y     , w2, h2, d, m);
     _nodes[2] = new QuadTreeXYAabb(x     , y + h2, w2, h2, d, m);
     _nodes[3] = new QuadTreeXYAabb(x + w2, y + h2, w2, h2, d, m);
   } else {
     _nodes[0].reset();
     _nodes[1].reset();
     _nodes[2].reset();
     _nodes[3].reset();
   }
   _isLeaf = false;
 }

 retrieve(Aabb3 v, List out) {
   var reg = findRegion(v);
   if (reg !=null && reg != this) {
     reg.retrieve(out, v);
   }
   for (var i = 1; i < _children.length; i +=2) {
     out.add(_children[i]);
   }
   return out;
 }

 scan(Function f) {
   for (var i = 1; i < _children.length; i +=2) {
     var a1 = _children[i];
     for (var j = i + 2; j < _children.length; j +=2) {
       f(a1, _children[j]);
     }
     _scanVsNodes(f, a1);
   }
   if (!_isLeaf) {
     for (var i = 0; i < 4; ++i) {
       _nodes[i].scan(f);
     }
   }
 }

 _scanVsNodes(Function f, a1) {
   if (_isLeaf) return;

   for (var i = 0; i < 4; ++i) {
     var n = _nodes[i];
     n._scanVsChildren(f, a1);
     n._scanVsNodes(f, a1);
   }
 }

 _scanVsChildren(Function f, a1) {
   for (var i = 1; i < _children.length; i +=2) {
     f(a1, _children[i]);
   }
 }

}

Constructors

new QuadTreeXYAabb(x, y, w, h, [int maxDepth = 4, int maxChildren = 4]) #

Creates a new Object instance.

Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.

docs inherited from Object
QuadTreeXYAabb(x, y, w, h, [this.maxDepth = 4, int maxChildren = 4]): this.maxChildren = maxChildren << 1 {
 _dim.min.setValues(x, y, 0.0);
 _dim.max.setValues(x + w, y + h, 0.0);
 _splitPoint.setFrom(_dim.min).add(_dim.max).scale(0.5);
}

Properties

final isLeaf #

get isLeaf => _isLeaf;

final int maxChildren #

The maximum number of children that a node can contain before it is split into sub-nodes.

final int maxChildren

final int maxDepth #

Whether the QuadTree will contain points (true), or items with bounds (width / height)(false).

final int maxDepth

final nbItems #

get nbItems => (_children.length >> 1) + ((_isLeaf)? 0 : (_nodes[0].nbItems + _nodes[1].nbItems + _nodes[2].nbItems + _nodes[3].nbItems));

final nbItemsL0 #

get nbItemsL0 => _children.length >> 1;

Methods

QuadTreeXYAabb findRegion(Aabb3 v) #

QuadTreeXYAabb findRegion(Aabb3 v) {
 if (v.min.x < _dim.min.x || v.max.x > _dim.max.x || (v.min.y < _dim.min.y) || v.max.y > _dim.max.y) {
   return null;
 }
 return _findRegion(v);
}

bool insert(Aabb3 v, obj) #

bool insert(Aabb3 v, obj) {
 var r = findRegion(v);
 if (r != null) {
   r._insert(v, obj);
//      if (this.maxDepth == 10) {
//        obj.ps.color[obj.i] = (r.maxDepth == 10)? 0x0000ffff : 0x00ff00ff;
//      }
 }
 return (r != null);
}

dynamic reset() #

use reset to reset the instance instead of create a new one with same bounds.

reset() {
 _children.clear();
 _isLeaf = true;
}

dynamic retrieve(Aabb3 v, List out) #

retrieve(Aabb3 v, List out) {
 var reg = findRegion(v);
 if (reg !=null && reg != this) {
   reg.retrieve(out, v);
 }
 for (var i = 1; i < _children.length; i +=2) {
   out.add(_children[i]);
 }
 return out;
}

dynamic scan(Function f) #

scan(Function f) {
 for (var i = 1; i < _children.length; i +=2) {
   var a1 = _children[i];
   for (var j = i + 2; j < _children.length; j +=2) {
     f(a1, _children[j]);
   }
   _scanVsNodes(f, a1);
 }
 if (!_isLeaf) {
   for (var i = 0; i < 4; ++i) {
     _nodes[i].scan(f);
   }
 }
}