blob: 5d5c1cb8735e8fe552da541bb3c6d375c6e68e91 [file] [log] [blame]
rileya@google.com1f45e932012-09-05 16:10:59 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
rileya@google.com1f45e932012-09-05 16:10:59 +00008#include "SkRTree.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +00009#include "SkRandom.h"
rileya@google.com1f45e932012-09-05 16:10:59 +000010#include "SkTSort.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000011#include "Test.h"
rileya@google.com1f45e932012-09-05 16:10:59 +000012
13static const size_t MIN_CHILDREN = 6;
14static const size_t MAX_CHILDREN = 11;
15
bsalomon@google.com373ebc62012-09-26 13:08:56 +000016static const int NUM_RECTS = 200;
rileya@google.com1f45e932012-09-05 16:10:59 +000017static const size_t NUM_ITERATIONS = 100;
18static const size_t NUM_QUERIES = 50;
19
mtklein533eb782014-08-27 10:39:42 -070020static SkRect random_rect(SkRandom& rand) {
21 SkRect rect = {0,0,0,0};
rileya@google.com1f45e932012-09-05 16:10:59 +000022 while (rect.isEmpty()) {
mtklein533eb782014-08-27 10:39:42 -070023 rect.fLeft = rand.nextRangeF(0, 1000);
24 rect.fRight = rand.nextRangeF(0, 1000);
25 rect.fTop = rand.nextRangeF(0, 1000);
26 rect.fBottom = rand.nextRangeF(0, 1000);
rileya@google.com1f45e932012-09-05 16:10:59 +000027 rect.sort();
28 }
29 return rect;
30}
31
mtklein6bd41962014-10-02 07:41:56 -070032static bool verify_query(SkRect query, SkRect rects[], SkTDArray<unsigned>& found) {
mtklein533eb782014-08-27 10:39:42 -070033 // TODO(mtklein): no need to do this after everything's SkRects
34 query.roundOut();
35
mtklein6bd41962014-10-02 07:41:56 -070036 SkTDArray<unsigned> expected;
mtklein533eb782014-08-27 10:39:42 -070037
rileya@google.com1f45e932012-09-05 16:10:59 +000038 // manually intersect with every rectangle
bsalomon@google.com373ebc62012-09-26 13:08:56 +000039 for (int i = 0; i < NUM_RECTS; ++i) {
mtklein6bd41962014-10-02 07:41:56 -070040 if (SkRect::Intersects(query, rects[i])) {
41 expected.push(i);
rileya@google.com1f45e932012-09-05 16:10:59 +000042 }
43 }
44
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000045 if (expected.count() != found.count()) {
46 return false;
47 }
48
rileya@google.com1f45e932012-09-05 16:10:59 +000049 if (0 == expected.count()) {
50 return true;
51 }
52
mtklein6bd41962014-10-02 07:41:56 -070053 // skia:2834. RTree doesn't always return results in order.
54 SkTQSort(expected.begin(), expected.end() -1);
55 SkTQSort(found.begin(), found.end() -1);
rileya@google.com1f45e932012-09-05 16:10:59 +000056 return found == expected;
57}
58
mtklein6bd41962014-10-02 07:41:56 -070059static void run_queries(skiatest::Reporter* reporter, SkRandom& rand, SkRect rects[],
rileya@google.com1f45e932012-09-05 16:10:59 +000060 SkRTree& tree) {
robertphillips@google.com178a2672012-09-13 13:25:30 +000061 for (size_t i = 0; i < NUM_QUERIES; ++i) {
mtklein6bd41962014-10-02 07:41:56 -070062 SkTDArray<unsigned> hits;
mtklein533eb782014-08-27 10:39:42 -070063 SkRect query = random_rect(rand);
rileya@google.com1f45e932012-09-05 16:10:59 +000064 tree.search(query, &hits);
65 REPORTER_ASSERT(reporter, verify_query(query, rects, hits));
66 }
67}
68
sglez@google.com8c902122013-08-30 17:27:47 +000069static void rtree_test_main(SkRTree* rtree, skiatest::Reporter* reporter) {
mtklein4477c3c2014-10-27 10:27:10 -070070 SkASSERT(rtree);
rileya@google.com1f45e932012-09-05 16:10:59 +000071
72 int expectedDepthMin = -1;
73 int expectedDepthMax = -1;
74
75 int tmp = NUM_RECTS;
76 while (tmp > 0) {
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000077 tmp -= static_cast<int>(pow(static_cast<double>(MAX_CHILDREN),
rileya@google.com1f45e932012-09-05 16:10:59 +000078 static_cast<double>(expectedDepthMin + 1)));
79 ++expectedDepthMin;
80 }
81
82 tmp = NUM_RECTS;
83 while (tmp > 0) {
84 tmp -= static_cast<int>(pow(static_cast<double>(MIN_CHILDREN),
85 static_cast<double>(expectedDepthMax + 1)));
86 ++expectedDepthMax;
87 }
88
mtklein4477c3c2014-10-27 10:27:10 -070089 SkRandom rand;
90 SkAutoTMalloc<SkRect> rects(NUM_RECTS);
robertphillips@google.com178a2672012-09-13 13:25:30 +000091 for (size_t i = 0; i < NUM_ITERATIONS; ++i) {
mtklein4477c3c2014-10-27 10:27:10 -070092 rtree->clear();
93 REPORTER_ASSERT(reporter, 0 == rtree->getCount());
rileya@google.com1f45e932012-09-05 16:10:59 +000094
mtklein4477c3c2014-10-27 10:27:10 -070095 for (int j = 0; j < NUM_RECTS; j++) {
96 rects[j] = random_rect(rand);
rileya@google.com1f45e932012-09-05 16:10:59 +000097 }
mtklein4477c3c2014-10-27 10:27:10 -070098
99 rtree->insert(&rects, NUM_RECTS);
100 SkASSERT(rects); // SkRTree doesn't take ownership of rects.
101
sglez@google.com8c902122013-08-30 17:27:47 +0000102 run_queries(reporter, rand, rects, *rtree);
rileya@google.com1f45e932012-09-05 16:10:59 +0000103 REPORTER_ASSERT(reporter, NUM_RECTS == rtree->getCount());
104 REPORTER_ASSERT(reporter, expectedDepthMin <= rtree->getDepth() &&
105 expectedDepthMax >= rtree->getDepth());
rileya@google.com1f45e932012-09-05 16:10:59 +0000106 }
107}
108
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000109DEF_TEST(RTree, reporter) {
sglez@google.com8c902122013-08-30 17:27:47 +0000110 SkRTree* rtree = SkRTree::Create(MIN_CHILDREN, MAX_CHILDREN);
111 SkAutoUnref au(rtree);
112 rtree_test_main(rtree, reporter);
113
114 // Rtree that orders input rectangles on deferred insert.
sglez@google.comffb71f22013-08-30 17:43:31 +0000115 SkRTree* unsortedRtree = SkRTree::Create(MIN_CHILDREN, MAX_CHILDREN, 1, false);
116 SkAutoUnref auo(unsortedRtree);
117 rtree_test_main(unsortedRtree, reporter);
sglez@google.com8c902122013-08-30 17:27:47 +0000118}