michael@0: /* michael@0: * Copyright 2014 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkQuadTree_DEFINED michael@0: #define SkQuadTree_DEFINED michael@0: michael@0: #include "SkRect.h" michael@0: #include "SkTDArray.h" michael@0: #include "SkBBoxHierarchy.h" michael@0: #include "SkTInternalSList.h" michael@0: #include "SkTObjectPool.h" michael@0: michael@0: /** michael@0: * A QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles michael@0: * in which each internal node has exactly four children. michael@0: * michael@0: * For more details see: michael@0: * michael@0: * http://en.wikipedia.org/wiki/Quadtree michael@0: */ michael@0: class SkQuadTree : public SkBBoxHierarchy { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkQuadTree) michael@0: michael@0: /** michael@0: * Quad tree constructor. michael@0: * @param bounds The bounding box for the root of the quad tree. michael@0: * giving the quad tree bounds that fall outside the root michael@0: * bounds may result in pathological but correct behavior. michael@0: */ michael@0: SkQuadTree(const SkIRect& bounds); michael@0: michael@0: virtual ~SkQuadTree(); michael@0: michael@0: /** michael@0: * Insert a node, consisting of bounds and a data value into the tree, if we don't immediately michael@0: * need to use the tree; we may allow the insert to be deferred (this can allow us to bulk-load michael@0: * a large batch of nodes at once, which tends to be faster and produce a better tree). michael@0: * @param data The data value michael@0: * @param bounds The corresponding bounding box michael@0: * @param defer Can this insert be deferred? (this may be ignored) michael@0: */ michael@0: virtual void insert(void* data, const SkIRect& bounds, bool defer = false) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * If any inserts have been deferred, this will add them into the tree michael@0: */ michael@0: virtual void flushDeferredInserts() SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Given a query rectangle, populates the passed-in array with the elements it intersects michael@0: */ michael@0: virtual void search(const SkIRect& query, SkTDArray* results) SK_OVERRIDE; michael@0: michael@0: virtual void clear() SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Gets the depth of the tree structure michael@0: */ michael@0: virtual int getDepth() const SK_OVERRIDE; michael@0: michael@0: /** michael@0: * This gets the insertion count (rather than the node count) michael@0: */ michael@0: virtual int getCount() const SK_OVERRIDE { return fEntryCount; } michael@0: michael@0: virtual void rewindInserts() SK_OVERRIDE; michael@0: michael@0: private: michael@0: struct Entry { michael@0: Entry() : fData(NULL) {} michael@0: SkIRect fBounds; michael@0: void* fData; michael@0: SK_DECLARE_INTERNAL_SLIST_INTERFACE(Entry); michael@0: }; michael@0: michael@0: static const int kChildCount = 4; michael@0: michael@0: struct Node { michael@0: Node() { michael@0: for (int index=0; index fEntries; michael@0: SkIRect fBounds; michael@0: SkIPoint fSplitPoint; // Only valid if the node has children. michael@0: Node* fChildren[kChildCount]; michael@0: SK_DECLARE_INTERNAL_SLIST_ADAPTER(Node, fChildren[0]); michael@0: }; michael@0: michael@0: SkTObjectPool fEntryPool; michael@0: SkTObjectPool fNodePool; michael@0: int fEntryCount; michael@0: Node* fRoot; michael@0: SkTInternalSList fDeferred; michael@0: michael@0: Node* pickChild(Node* node, const SkIRect& bounds) const; michael@0: void insert(Node* node, Entry* entry); michael@0: void search(Node* node, const SkIRect& query, SkTDArray* results) const; michael@0: void clear(Node* node); michael@0: int getDepth(Node* node) const; michael@0: michael@0: typedef SkBBoxHierarchy INHERITED; michael@0: }; michael@0: michael@0: #endif