1 // Copyright 2017 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 16 // Original Author: ericv@google.com (Eric Veach) 17 // Converted to D: vnayar@gmail.com (Vijay Nayar) 18 19 module s2.s2distance_target; 20 21 import s2.s2cap; 22 import s2.s2cell; 23 import s2.s2point; 24 import s2.s2shape; 25 import s2.s2shape_index; 26 27 /** 28 * S2DistanceTarget represents a geometric object to which distances are 29 * measured. For example, there are subtypes for measuring distances to a 30 * point, an edge, or to an S2ShapeIndex (an arbitrary collection of 31 * geometry). S2DistanceTarget objects are provided for the benefit of 32 * classes that measure distances and/or find nearby geometry, such as 33 * S2ClosestEdgeQuery and S2ClosestPointQuery. 34 * 35 * Implementations do *not* need to be thread-safe. They may cache data or 36 * allocate temporary data structures in order to improve performance. For 37 * this reason, S2DistanceTarget objects are typically passed as pointers 38 * rather than as const references. 39 * 40 * The Distance template argument is used to represent distances. Usually 41 * this type is a thin wrapper around S1ChordAngle, but another distance type 42 * may be substituted as long as it implements the API below. This can be 43 * used to change the comparison function (e.g., to find the furthest edges 44 * from the target), or to get more accuracy if desired. 45 * 46 * The Distance concept is as follows: 47 * 48 * class Distance { 49 * public: 50 * // Default and copy constructors, assignment operator: 51 * Distance(); 52 * Distance(const Distance&); 53 * Distance& operator=(const Distance&); 54 * 55 * // Factory methods: 56 * static Distance Zero(); // Returns a zero distance. 57 * static Distance Infinity(); // Larger than any valid distance. 58 * static Distance Negative(); // Smaller than any valid distance. 59 * 60 * // Comparison operators: 61 * friend bool operator==(Distance x, Distance y); 62 * friend bool operator<(Distance x, Distance y); 63 * 64 * // Delta represents the positive difference between two distances. 65 * // It is used together with operator-() to implement Options::max_error(). 66 * // Typically Distance::Delta is simply S1ChordAngle. 67 * class Delta { 68 * public: 69 * Delta(); 70 * Delta(const Delta&); 71 * Delta& operator=(const Delta&); 72 * friend bool operator==(Delta x, Delta y); 73 * static Delta Zero(); 74 * }; 75 * 76 * // Subtraction operator. Note that the second argument represents a 77 * // delta between two distances. This distinction is important for 78 * // classes that compute maximum distances (e.g., S2FurthestEdgeQuery). 79 * friend Distance operator-(Distance x, Delta delta); 80 * 81 * // Method that returns an upper bound on the S1ChordAngle corresponding 82 * // to this Distance (needed to implement Options::max_distance 83 * // efficiently). For example, if Distance measures WGS84 ellipsoid 84 * // distance then the corresponding angle needs to be 0.56% larger. 85 * S1ChordAngle GetChordAngleBound() const; 86 * }; 87 */ 88 abstract class S2DistanceTarget(DistanceT) { 89 public: 90 alias Delta = DistanceT.Delta; 91 92 /** 93 * Returns an S2Cap that bounds the set of points whose distance to the 94 * target is DistanceT::Zero(). 95 */ 96 abstract S2Cap getCapBound(); 97 98 /** 99 * If the distance to the point "p" "min_dist", then updates "min_dist" and 100 * returns true. Otherwise returns false. 101 */ 102 abstract bool updateMinDistance(in S2Point p, ref DistanceT min_dist); 103 104 /** 105 * If the distance to the edge (v0, v1) is less than "min_dist", then 106 * updates "min_dist" and returns true. Otherwise returns false. 107 */ 108 abstract bool updateMinDistance(in S2Point v0, in S2Point v1, ref DistanceT min_dist); 109 110 /** 111 * If the distance to the given S2Cell (including its interior) is less 112 * than "min_dist", then updates "min_dist" and returns true. Otherwise 113 * returns false. 114 */ 115 abstract bool updateMinDistance(in S2Cell cell, ref DistanceT min_dist); 116 117 /** 118 * Finds all polygons in the given "query_index" that completely contain a 119 * connected component of the target geometry. (For example, if the 120 * target consists of 10 points, this method finds polygons that contain 121 * any of those 10 points.) For each such polygon, "visitor" is called 122 * with the S2Shape of the polygon along with a point of the target 123 * geometry that is contained by that polygon. 124 * 125 * Optionally, any polygon that intersects the target geometry may also be 126 * returned. In other words, this method returns all polygons that 127 * contain any connected component of the target, along with an arbitrary 128 * subset of the polygons that intersect the target. 129 * 130 * For example, suppose that "query_index" contains two abutting polygons 131 * A and B. If the target consists of two points "a" contained by A and 132 * "b" contained by B, then both A and B are returned. But if the target 133 * consists of the edge "ab", then any subset of {A, B} could be returned 134 * (because both polygons intersect the target but neither one contains 135 * the edge "ab"). 136 * 137 * If "visitor" returns false, this method terminates early and returns 138 * false as well. Otherwise returns true. 139 * 140 * NOTE(ericv): This method exists only for the purpose of implementing 141 * S2ClosestEdgeQuery::Options::include_interiors() efficiently. Its API is 142 * unlikely to be useful for other purposes. 143 */ 144 alias ShapeVisitor = bool delegate(in S2Shape containing_shape, in S2Point target_point); 145 146 abstract bool visitContainingShapes(S2ShapeIndex query_index, ShapeVisitor visitor); 147 148 /** 149 * Specifies that whenever one of the UpdateMinDistance() methods above 150 * returns "true", the returned distance is allowed to be up to "max_error" 151 * larger than the true minimum distance. In other words, it gives this 152 * target object permission to terminate its distance calculation as soon as 153 * it has determined that (1) the minimum distance is less than "min_dist" 154 * and (2) the best possible further improvement is less than "max_error". 155 * 156 * If the target takes advantage of "max_error" to optimize its distance 157 * calculation, this method must return "true". (Most target types can use 158 * the default implementation which simply returns false.) 159 */ 160 bool setMaxError(in Delta max_error) { 161 return false; 162 } 163 164 /** 165 * The following method is provided as a convenience for classes that 166 * compute distances to a collection of indexed geometry, such as 167 * S2ClosestEdgeQuery and S2ClosestPointQuery. It returns the maximum 168 * number of indexed objects for which it is faster to compute the distance 169 * by brute force (e.g., by testing every edge) rather than by using an 170 * index. (The appropriate value is different for each index type and can 171 * be estimated for a given (distance target, index type) pair by running 172 * benchmarks.) 173 * 174 * By default this method returns -1, indicating that it is not implemented. 175 */ 176 int maxBruteForceIndexSize() const { 177 return -1; 178 } 179 }