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 }