-
Notifications
You must be signed in to change notification settings - Fork 181
/
query_options.go
196 lines (176 loc) · 7.83 KB
/
query_options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package s2
import (
"math"
"github.com/golang/geo/s1"
)
const maxQueryResults = math.MaxInt32
// queryOptions represents the set of all configurable parameters used by all of
// the Query types. Most of these fields have non-zero defaults, so initialization
// is handled within each Query type. All of the exported methods accept user
// supplied sets of options to set or adjust as necessary.
//
// Several of the defaults depend on the distance interface type being used
// (e.g. minDistance, maxDistance, etc.)
//
// If a user sets an option value that a given query type doesn't use, it is ignored.
type queryOptions struct {
// maxResults specifies that at most MaxResults edges should be returned.
// This must be at least 1.
//
// The default value is to return all results.
maxResults int
// distanceLimit specifies that only edges whose distance to the target is
// within this distance should be returned.
//
// Note that edges whose distance is exactly equal to this are
// not returned. In most cases this doesn't matter (since distances are
// not computed exactly in the first place), but if such edges are needed
// then you can retrieve them by specifying the distance as the next
// largest representable distance. i.e. distanceLimit.Successor().
//
// The default value is the infinity value, such that all results will be
// returned.
distanceLimit s1.ChordAngle
// maxError specifies that edges up to MaxError further away than the true
// closest edges may be substituted in the result set, as long as such
// edges satisfy all the remaining search criteria (such as DistanceLimit).
// This option only has an effect if MaxResults is also specified;
// otherwise all edges closer than MaxDistance will always be returned.
//
// Note that this does not affect how the distance between edges is
// computed; it simply gives the algorithm permission to stop the search
// early as soon as the best possible improvement drops below MaxError.
//
// This can be used to implement distance predicates efficiently. For
// example, to determine whether the minimum distance is less than D, set
// MaxResults == 1 and MaxDistance == MaxError == D. This causes
// the algorithm to terminate as soon as it finds any edge whose distance
// is less than D, rather than continuing to search for an edge that is
// even closer.
//
// The default value is zero.
maxError s1.ChordAngle
// includeInteriors specifies that polygon interiors should be included
// when measuring distances. In other words, polygons that contain the target
// should have a distance of zero. (For targets consisting of multiple connected
// components, the distance is zero if any component is contained.) This
// is indicated in the results by returning a (ShapeID, EdgeID) pair
// with EdgeID == -1, i.e. this value denotes the polygons's interior.
//
// Note that for efficiency, any polygon that intersects the target may or
// may not have an EdgeID == -1 result. Such results are optional
// because in that case the distance to the polygon is already zero.
//
// The default value is true.
includeInteriors bool
// specifies that distances should be computed by examining every edge
// rather than using the ShapeIndex.
//
// TODO(roberts): When optimized is implemented, update the default to false.
// The default value is true.
useBruteForce bool
// region specifies that results must intersect the given Region.
//
// Note that if you want to set the region to a disc around a target
// point, it is faster to use a PointTarget with distanceLimit set
// instead. You can also set a distance limit and also require that results
// lie within a given rectangle.
//
// The default is nil (no region limits).
region Region
}
// UseBruteForce sets or disables the use of brute force in a query.
func (q *queryOptions) UseBruteForce(x bool) *queryOptions {
q.useBruteForce = x
return q
}
// IncludeInteriors specifies whether polygon interiors should be
// included when measuring distances.
func (q *queryOptions) IncludeInteriors(x bool) *queryOptions {
q.includeInteriors = x
return q
}
// MaxError specifies that edges up to dist away than the true
// matching edges may be substituted in the result set, as long as such
// edges satisfy all the remaining search criteria (such as DistanceLimit).
// This option only has an effect if MaxResults is also specified;
// otherwise all edges closer than MaxDistance will always be returned.
func (q *queryOptions) MaxError(x s1.ChordAngle) *queryOptions {
q.maxError = x
return q
}
// MaxResults specifies that at most MaxResults edges should be returned.
// This must be at least 1.
func (q *queryOptions) MaxResults(x int) *queryOptions {
// TODO(roberts): What should be done if the value is <= 0?
q.maxResults = int(x)
return q
}
// DistanceLimit specifies that only edges whose distance to the target is
// within, this distance should be returned. Edges whose distance is equal
// are not returned.
//
// To include values that are equal, specify the limit with the next largest
// representable distance such as limit.Successor(), or set the option with
// Furthest/ClosestInclusiveDistanceLimit.
func (q *queryOptions) DistanceLimit(x s1.ChordAngle) *queryOptions {
q.distanceLimit = x
return q
}
// ClosestInclusiveDistanceLimit sets the distance limit such that results whose
// distance is exactly equal to the limit are also returned.
func (q *queryOptions) ClosestInclusiveDistanceLimit(limit s1.ChordAngle) *queryOptions {
q.distanceLimit = limit.Successor()
return q
}
// FurthestInclusiveDistanceLimit sets the distance limit such that results whose
// distance is exactly equal to the limit are also returned.
func (q *queryOptions) FurthestInclusiveDistanceLimit(limit s1.ChordAngle) *queryOptions {
q.distanceLimit = limit.Predecessor()
return q
}
// ClosestConservativeDistanceLimit sets the distance limit such that results
// also incorporates the error in distance calculations. This ensures that all
// edges whose true distance is less than or equal to limit will be returned
// (along with some edges whose true distance is slightly greater).
//
// Algorithms that need to do exact distance comparisons can use this
// option to find a set of candidate edges that can then be filtered
// further (e.g., using CompareDistance).
func (q *queryOptions) ClosestConservativeDistanceLimit(limit s1.ChordAngle) *queryOptions {
q.distanceLimit = limit.Expanded(minUpdateDistanceMaxError(limit))
return q
}
// FurthestConservativeDistanceLimit sets the distance limit such that results
// also incorporates the error in distance calculations. This ensures that all
// edges whose true distance is greater than or equal to limit will be returned
// (along with some edges whose true distance is slightly less).
func (q *queryOptions) FurthestConservativeDistanceLimit(limit s1.ChordAngle) *queryOptions {
q.distanceLimit = limit.Expanded(-minUpdateDistanceMaxError(limit))
return q
}
// newQueryOptions returns a set of options using the given distance type
// with the proper default values.
func newQueryOptions(d distance) *queryOptions {
return &queryOptions{
maxResults: maxQueryResults,
distanceLimit: d.infinity().chordAngle(),
maxError: 0,
includeInteriors: true,
useBruteForce: false,
region: nil,
}
}