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: madric@gmail.com (Vijay Nayar) 18 19 module s2.s2contains_vertex_query; 20 21 import s2.s2point; 22 import s2.s2pointutil : ortho; 23 import s2.s2predicates : orderedCCW; 24 25 import std.exception : enforce; 26 import std.math : abs; 27 import std.typecons : tuple; 28 29 // This class determines whether a polygon contains one of its vertices given 30 // the edges incident to that vertex. The result is +1 if the vertex is 31 // contained, -1 if it is not contained, and 0 if the incident edges consist 32 // of matched sibling pairs (in which case the result cannot be determined 33 // locally). 34 // 35 // Point containment is defined according to the "semi-open" boundary model 36 // (see S2VertexModel), which means that if several polygons tile the region 37 // around a vertex, then exactly one of those polygons contains that vertex. 38 // 39 // This class is not thread-safe. To use it in parallel, each thread should 40 // construct its own instance (this is not expensive). 41 class S2ContainsVertexQuery { 42 public: 43 // "target" is the vertex whose containment will be determined. 44 this(in S2Point target) { 45 _target = target; 46 } 47 48 // Indicates that the polygon has an edge between "target" and "v" in the 49 // given direction (+1 = outgoing, -1 = incoming, 0 = degenerate). 50 void addEdge(in S2Point v, int direction) { 51 _edgeMap[v] += direction; 52 } 53 54 // Returns +1 if the vertex is contained, -1 if it is not contained, and 0 55 // if the incident edges consisted of matched sibling pairs. 56 int containsSign() { 57 // Find the unmatched edge that is immediately clockwise from S2::Ortho(P). 58 S2Point reference_dir = ortho(_target); 59 auto best = tuple(reference_dir, 0); 60 foreach (S2Point point, int dir; _edgeMap) { 61 enforce(abs(dir) <= 1); 62 if (dir == 0) continue; // This is a "matched" edge. 63 if (orderedCCW(reference_dir, best[0], point, _target)) { 64 best = tuple(point, dir); 65 } 66 } 67 return best[1]; 68 } 69 70 private: 71 S2Point _target; 72 int[S2Point] _edgeMap; 73 }