UNPKG

8.35 kBTypeScriptView Raw
1// Last module patch version validated against: 3.0.1
2
3/**
4 * Leaf node of the quadtree.
5 */
6export interface QuadtreeLeaf<T> {
7 /**
8 * The data associated with this point, as passed to quadtree.add.
9 */
10 data: T;
11
12 /**
13 * The next datum in this leaf, if any.
14 */
15 next?: QuadtreeLeaf<T> | undefined;
16
17 /**
18 * The length property may be used to distinguish leaf nodes from internal nodes: it is undefined for leaf nodes, and 4 for internal nodes.
19 */
20 length?: undefined;
21}
22
23/**
24 * Internal nodes of the quadtree are represented as four-element arrays in left-to-right, top-to-bottom order:
25 *
26 * 0 - the top-left quadrant, if any.
27 * 1 - the top-right quadrant, if any.
28 * 2 - the bottom-left quadrant, if any.
29 * 3 - the bottom-right quadrant, if any.
30 *
31 * A child quadrant may be undefined if it is empty.
32 */
33export interface QuadtreeInternalNode<T> extends Array<QuadtreeInternalNode<T> | QuadtreeLeaf<T> | undefined> {
34 /**
35 * The length property may be used to distinguish leaf nodes from internal nodes: it is undefined for leaf nodes, and 4 for internal nodes.
36 */
37 length: 4;
38}
39
40export interface Quadtree<T> {
41 /**
42 * Returns the current x-accessor, which defaults to: `x(d) => d[0]`.
43 */
44 x(): (d: T) => number;
45 /**
46 * Sets the current x-coordinate accessor and returns the quadtree.
47 * The x-accessors must be consistent, returning the same value given the same input.
48 *
49 * @param x The x-coordinate accessor.
50 */
51 x(x: (d: T) => number): this;
52
53 /**
54 * Returns the current y-accessor, which defaults to: `y(d) => d[1]`.
55 */
56 y(): (d: T) => number;
57 /**
58 * Sets the current y-coordinate accessor and returns the quadtree.
59 * The y-accessors must be consistent, returning the same value given the same input.
60 *
61 * @param y The y-coordinate accessor.
62 */
63 y(y: (d: T) => number): this;
64
65 /**
66 * Returns the quadtree's current extent `[[x0, y0], [x1, y1]]`,
67 * where `x0` and `y0` are the inclusive lower bounds and `x1` and `y1` are the inclusive upper bounds,
68 * or `undefined` if the quadtree has no extent.
69 */
70 extent(): [[number, number], [number, number]] | undefined;
71 /**
72 * Expands the quadtree to cover the specified points `[[x0, y0], [x1, y1]]` and returns the quadtree.
73 * The extent may also be expanded by calling `quadtree.cover` or `quadtree.add`.
74 *
75 * @param extend The specified points to cover.
76 */
77 extent(extend: [[number, number], [number, number]]): this;
78
79 /**
80 * Expands the quadtree to cover the specified point ⟨x,y⟩, and returns the quadtree.
81 * * If the quadtree’s extent already covers the specified point, this method does nothing.
82 * * If the quadtree has an extent, the extent is repeatedly doubled to cover the specified point, wrapping the root node as necessary.
83 * * If the quadtree is empty, the extent is initialized to the extent `[[⌊x⌋, ⌊y⌋], [⌈x⌉, ⌈y⌉]]`.
84 * Rounding is necessary such that if the extent is later doubled, the boundaries of existing quadrants do not change due to floating point error.
85 *
86 * @param x The x-coordinate for the specified point to cover.
87 * @param y The y-coordinate for the specified point to cover.
88 */
89 cover(x: number, y: number): this;
90
91 /**
92 * Adds the specified datum to the quadtree, deriving its coordinates ⟨x,y⟩ using the current x- and y-accessors, and returns the quadtree.
93 * If the new point is outside the current extent of the quadtree, the quadtree is automatically expanded to cover the new point.
94 *
95 * @param datum The specified datum to add.
96 */
97 add(datum: T): this;
98
99 /**
100 * Adds the specified array of data to the quadtree, deriving each element’s coordinates ⟨x,y⟩ using the current x- and y-accessors, and return this quadtree.
101 * This is approximately equivalent to calling quadtree.add repeatedly.
102 * However, this method results in a more compact quadtree because the extent of the data is computed first before adding the data.
103 *
104 * @param data The specified array of data to add.
105 */
106 addAll(data: T[]): this;
107
108 /**
109 * Removes the specified datum to the quadtree, deriving its coordinates ⟨x,y⟩ using the current x- and y-accessors, and returns the quadtree.
110 * If the specified datum does not exist in this quadtree, this method does nothing.
111 *
112 * @param datum The specified datum to remove.
113 */
114 remove(datum: T): this;
115
116 /**
117 * Removes the specified data to the quadtree, deriving their coordinates ⟨x,y⟩ using the current x- and y-accessors, and returns the quadtree.
118 * If a specified datum does not exist in this quadtree, it is ignored.
119 *
120 * @param data The specified array of data to remove.
121 */
122 removeAll(data: T[]): this;
123
124 /**
125 * Returns a copy of the quadtree. All nodes in the returned quadtree are identical copies of the corresponding node in the quadtree;
126 * however, any data in the quadtree is shared by reference and not copied.
127 */
128 copy(): Quadtree<T>;
129
130 /**
131 * Returns the root node of the quadtree.
132 */
133 root(): QuadtreeInternalNode<T> | QuadtreeLeaf<T>;
134
135 /**
136 * Returns an array of all data in the quadtree.
137 */
138 data(): T[];
139
140 /**
141 * Returns the total number of data in the quadtree.
142 */
143 size(): number;
144
145 /**
146 * Returns the datum closest to the position ⟨x,y⟩ with the given search radius. If radius is not specified, it defaults to infinity.
147 * If there is no datum within the search area, returns undefined.
148 *
149 * @param x The x-coordinate for the search position.
150 * @param y The y-coordinate for the search position.
151 * @param radius The optional search radius.
152 */
153 find(x: number, y: number, radius?: number): T | undefined;
154
155 /**
156 * Visits each node in the quadtree in pre-order traversal, invoking the specified callback with arguments `node`, `x0`, `y0`, `x1`, `y1` for each node,
157 * where `node` is the node being visited, ⟨x0, y0⟩ are the lower bounds of the node, and ⟨x1, y1⟩ are the upper bounds, and returns the quadtree.
158 *
159 * If the callback returns true for a given node, then the children of that node are not visited; otherwise, all child nodes are visited.
160 * This can be used to quickly visit only parts of the tree.
161 * Note, however, that child quadrants are always visited in sibling order: top-left, top-right, bottom-left, bottom-right.
162 * In cases such as search, visiting siblings in a specific order may be faster.
163 *
164 * @param callback The callback invoked for each node.
165 */
166 visit(
167 callback: (
168 node: QuadtreeInternalNode<T> | QuadtreeLeaf<T>,
169 x0: number,
170 y0: number,
171 x1: number,
172 y1: number,
173 // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
174 ) => void | boolean,
175 ): this;
176
177 /**
178 * Visits each node in the quadtree in post-order traversal, invoking the specified callback with arguments `node`, `x0`, `y0`, `x1`, `y1` for each node,
179 * where `node` is the node being visited, ⟨x0, y0⟩ are the lower bounds of the node, and ⟨x1, y1⟩ are the upper bounds, and returns the quadtree.
180 *
181 * @param callback The callback invoked for each node.
182 */
183 visitAfter(
184 callback: (
185 node: QuadtreeInternalNode<T> | QuadtreeLeaf<T>,
186 x0: number,
187 y0: number,
188 x1: number,
189 y1: number,
190 ) => void,
191 ): this;
192}
193
194/**
195 * Creates a new, empty quadtree with an empty extent and the default x- and y-accessors.
196 * If data is specified, adds the specified array of data to the quadtree.
197 */
198export function quadtree<T = [number, number]>(data?: T[]): Quadtree<T>;
199/**
200 * Creates a new, empty quadtree with an empty extent and the default x- and y-accessors.
201 * Adds the specified array of data to the quadtree.
202 * Sets the x- and y- accessors to the specified functions before adding the specified array of data to the quadtree.
203 */
204export function quadtree<T = [number, number]>(data: T[], x: (d: T) => number, y: (d: T) => number): Quadtree<T>;