query method

QuadTree$QueryResult query(
  1. Rect rect
)

Query the QuadTree for objects that intersect with the given rect. Returns a buffer of object data.

Implementation

QuadTree$QueryResult query(ui.Rect rect) {
  //if (rect.isEmpty) return QuadTree$QueryResult._(Float32List(0));

  final root = _root;
  if (root == null || isEmpty) return QuadTree$QueryResult._(Float32List(0));

  const sizePerObject = QuadTree$QueryResult.sizePerObject; // id + 4 floats
  final objects = _objects;
  var offset = 0;

  // If the query rectangle fully contains the QuadTree boundary.
  // Return all objects in the QuadTree.
  if (rect.left <= boundary.left &&
      rect.top <= boundary.top &&
      rect.right >= boundary.right &&
      rect.bottom >= boundary.bottom) {
    final results = Float32List(_length * sizePerObject);
    final ids = Uint32List.sublistView(results);

    if (root._subdivided) {
      for (var i = 0, j = 0; i < _nextObjectId; i++) {
        if (_id2node[i] == 0) continue;
        offset = i * _objectSize;
        ids[j + 0] = i;
        results[j + 1] = objects[offset + 0];
        results[j + 2] = objects[offset + 1];
        results[j + 3] = objects[offset + 2];
        results[j + 4] = objects[offset + 3];
        j += sizePerObject;
      }
    } else {
      final rootIds = root._ids;
      var j = 0;
      for (final id in rootIds) {
        offset = id * _objectSize;
        ids[j + 0] = id;
        results[j + 1] = objects[offset + 0];
        results[j + 2] = objects[offset + 1];
        results[j + 3] = objects[offset + 2];
        results[j + 4] = objects[offset + 3];
        j += sizePerObject;
      }
    }
    return QuadTree$QueryResult._(results);
  }

  final subdivided = Queue<QuadTree$Node>()..add(root);
  final leafs = <QuadTree$Node>[];

  // Find all leaf nodes from the subdivided nodes
  while (subdivided.isNotEmpty) {
    final node = subdivided.removeFirst();
    if (node.isEmpty) continue;
    if (!_overlaps(node.boundary, rect)) continue;
    if (node.subdivided) {
      subdivided
        ..add(node._northWest!)
        ..add(node._northEast!)
        ..add(node._southWest!)
        ..add(node._southEast!);
    } else {
      leafs.add(node);
    }
  }

  // Find all objects in the leaf nodes
  // hat intersect with the query rectangle
  /* var j = 0;
  for (var i = 0; i < leafs.length; i++) {
    final node = leafs[i];
    if (!_overlaps(node.boundary, rect)) continue;
    if (i != j) leafs[j] = leafs[i];
    j++;
  }
  leafs.length = j; */

  // No leaf nodes found
  if (leafs.isEmpty) return QuadTree$QueryResult._(Float32List(0));

  // Calculate the maximum possible length of the results
  final length = leafs.fold<int>(0, (sum, node) => sum + node.length);

  // Fill the results with the objects from the leaf nodes
  final results = Float32List(length * sizePerObject);
  final ids = Uint32List.sublistView(results);
  var $length = 0;
  for (final node in leafs) {
    for (final id in node._ids) {
      offset = id * _objectSize;
      final left = objects[offset + 0],
          top = objects[offset + 1],
          width = objects[offset + 2],
          height = objects[offset + 3];
      if (!_overlapsLTWH(rect, left, top, width, height)) continue;
      ids[$length + 0] = id;
      results[$length + 1] = left;
      results[$length + 2] = top;
      results[$length + 3] = width;
      results[$length + 4] = height;
      $length += sizePerObject;
    }
  }

  // No objects found
  if ($length == 0) return QuadTree$QueryResult._(Float32List(0));

  // Resize the results to the actual length
  return QuadTree$QueryResult._(results.sublist(0, $length));
}