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