Coverage Report

Created: 2026-08-13 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/index/quadtree/Root.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2006 Refractions Research Inc.
7
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
8
 *
9
 * This is free software; you can redistribute and/or modify it under
10
 * the terms of the GNU Lesser General Public Licence as published
11
 * by the Free Software Foundation.
12
 * See the COPYING file for more information.
13
 *
14
 **********************************************************************
15
 *
16
 * Last port: index/quadtree/Root.java rev 1.7 (JTS-1.10)
17
 *
18
 **********************************************************************/
19
20
#include <geos/index/quadtree/Root.h>
21
#include <geos/index/quadtree/Node.h>
22
#include <geos/index/quadtree/IntervalSize.h>
23
#include <geos/geom/Coordinate.h>
24
#include <geos/geom/Envelope.h>
25
#include <geos/util/IllegalArgumentException.h>
26
27
#include <cassert>
28
29
#ifndef GEOS_DEBUG
30
#define GEOS_DEBUG 0
31
#endif
32
33
#if GEOS_DEBUG
34
#include <iostream>
35
#endif
36
37
using namespace geos::geom;
38
39
namespace geos {
40
namespace index { // geos.index
41
namespace quadtree { // geos.index.quadtree
42
43
// the singleton root quad is centred at the origin.
44
//Coordinate* Root::origin=new Coordinate(0.0, 0.0);
45
const Coordinate Root::origin(0.0, 0.0);
46
47
/*public*/
48
void
49
Root::insert(const Envelope* itemEnv, void* item)
50
129k
{
51
52
#if GEOS_DEBUG
53
    std::cerr << "Root(" << this << ")::insert(" << itemEnv->toString() << ", " << item << ") called" << std::endl;
54
#endif
55
129k
    if (!itemEnv->isfinite()) {
56
4.08k
        throw util::IllegalArgumentException("Non-finite envelope bounds passed to index insert");
57
4.08k
    }
58
125k
    int index = getSubnodeIndex(itemEnv, origin);
59
    // if index is -1, itemEnv must cross the X or Y axis.
60
125k
    if(index == -1) {
61
#if GEOS_DEBUG
62
        std::cerr << "  -1 subnode index" << std::endl;
63
#endif
64
24.5k
        add(item);
65
24.5k
        return;
66
24.5k
    }
67
68
    /*
69
     * the item must be contained in one quadrant, so insert it into the
70
     * tree for that quadrant (which may not yet exist)
71
     */
72
101k
    Node* node = subnodes[static_cast<std::size_t>(index)];
73
74
#if GEOS_DEBUG
75
    std::cerr << "(" << this << ") subnode[" << index << "] @ " << node << std::endl;
76
#endif
77
78
    /*
79
     *  If the subquad doesn't exist or this item is not contained in it,
80
     *  have to expand the tree upward to contain the item.
81
     */
82
101k
    if(node == nullptr || !node->getEnvelope()->contains(itemEnv)) {
83
21.2k
        std::unique_ptr<Node> snode(node);  // may be NULL
84
21.2k
        node = nullptr;
85
21.2k
        subnodes[static_cast<std::size_t>(index)] = nullptr;
86
87
21.2k
        std::unique_ptr<Node> largerNode =
88
21.2k
            Node::createExpanded(std::move(snode), *itemEnv);
89
90
#if GEOS_DEBUG
91
        std::cerr << "(" << this << ") created expanded node " << largerNode.get() << " containing previously reported subnode"
92
                  << std::endl;
93
#endif
94
95
        // Previous subnode was passed as a child of the larger one
96
21.2k
        assert(!subnodes[static_cast<std::size_t>(index)]);
97
21.2k
        subnodes[static_cast<std::size_t>(index)] = largerNode.release();
98
21.2k
    }
99
100
#if GEOS_DEBUG
101
    std::cerr << "(" << this << ") calling insertContained with subnode " << subnodes[index] << std::endl;
102
#endif
103
    /*
104
     * At this point we have a subquad which exists and must contain
105
     * contains the env for the item.  Insert the item into the tree.
106
     */
107
101k
    insertContained(subnodes[static_cast<std::size_t>(index)], itemEnv, item);
108
109
#if GEOS_DEBUG
110
    std::cerr << "(" << this << ") done calling insertContained with subnode " << subnodes[index] << std::endl;
111
#endif
112
113
    //System.out.println("depth = " + root.depth() + " size = " + root.size());
114
    //System.out.println(" size = " + size());
115
101k
}
116
117
/*private*/
118
void
119
Root::insertContained(Node* tree, const Envelope* itemEnv, void* item)
120
101k
{
121
101k
    assert(tree->getEnvelope()->contains(itemEnv));
122
123
    /*
124
     * Do NOT create a new quad for zero-area envelopes - this would lead
125
     * to infinite recursion. Instead, use a heuristic of simply returning
126
     * the smallest existing quad containing the query
127
     */
128
101k
    bool isZeroX = IntervalSize::isZeroWidth(itemEnv->getMinX(),
129
101k
                   itemEnv->getMaxX());
130
101k
    bool isZeroY = IntervalSize::isZeroWidth(itemEnv->getMinY(),
131
101k
                   itemEnv->getMaxY());
132
133
101k
    NodeBase* node;
134
135
101k
    if(isZeroX || isZeroY) {
136
11.6k
        node = tree->find(itemEnv);
137
11.6k
    }
138
89.4k
    else {
139
89.4k
        node = tree->getNode(itemEnv);
140
89.4k
    }
141
142
101k
    node->add(item);
143
101k
}
144
145
} // namespace geos.index.quadtree
146
} // namespace geos.index
147
} // namespace geos