1 // Copyright 2013 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.s2error;
20 
21 import std.format : format;
22 
23 /**
24  * S2Error is a simple class consisting of an error code and a human-readable
25  * error message.
26  *
27  * This class is intended to be copied by value as desired.  It uses
28  * the default copy constructor and assignment operator.
29  */
30 struct S2Error {
31 private:
32   Code _code = Code.OK;
33   string _text;
34 
35 public:
36   enum Code {
37     OK = 0,                  // No error.
38 
39     ////////////////////////////////////////////////////////////////////
40     // Generic errors, not specific to geometric objects:
41 
42     UNKNOWN = 1000,              // Unknown error.
43     UNIMPLEMENTED = 1001,        // Operation is not implemented.
44     OUT_OF_RANGE = 1002,         // Argument is out of range.
45     INVALID_ARGUMENT = 1003,     // Invalid argument (other than a range error).
46     FAILED_PRECONDITION = 1004,  // Object is not in the required state.
47     INTERNAL = 1005,             // An internal invariant has failed.
48     DATA_LOSS = 1006,            // Data loss or corruption.
49     RESOURCE_EXHAUSTED = 1007,   // A resource has been exhausted.
50 
51     ////////////////////////////////////////////////////////////////////
52     // Error codes in the following range can be defined by clients:
53 
54     USER_DEFINED_START = 1000000,
55     USER_DEFINED_END   = 9999999,
56 
57     ////////////////////////////////////////////////////////////////////
58     // Errors that apply to more than one type of geometry:
59 
60     NOT_UNIT_LENGTH = 1,     // Vertex is not unit length.
61     DUPLICATE_VERTICES = 2,  // There are two identical vertices.
62     ANTIPODAL_VERTICES = 3,  // There are two antipodal vertices.
63 
64     ////////////////////////////////////////////////////////////////////
65     // S2Loop errors:
66 
67     LOOP_NOT_ENOUGH_VERTICES = 100,  // Loop with fewer than 3 vertices.
68     LOOP_SELF_INTERSECTION = 101,    // Loop has a self-intersection.
69 
70     ////////////////////////////////////////////////////////////////////
71     // S2Polygon errors:
72 
73     POLYGON_LOOPS_SHARE_EDGE = 200,  // Two polygon loops share an edge.
74     POLYGON_LOOPS_CROSS = 201,       // Two polygon loops cross.
75     POLYGON_EMPTY_LOOP = 202,        // Polygon has an empty loop.
76     POLYGON_EXCESS_FULL_LOOP = 203,  // Non-full polygon has a full loop.
77 
78     // InitOriented() was called and detected inconsistent loop orientations.
79     POLYGON_INCONSISTENT_LOOP_ORIENTATIONS = 204,
80 
81     // Loop depths don't correspond to any valid nesting hierarchy.
82     POLYGON_INVALID_LOOP_DEPTH = 205,
83 
84     // Actual polygon nesting does not correspond to the nesting hierarchy
85     // encoded by the loop depths.
86     POLYGON_INVALID_LOOP_NESTING = 206,
87 
88     ////////////////////////////////////////////////////////////////////
89     // S2Builder errors:
90 
91     // The S2Builder snap function moved a vertex by more than the specified
92     // snap radius.
93     BUILDER_SNAP_RADIUS_TOO_SMALL = 300,
94 
95     // S2Builder expected all edges to have siblings (as specified by
96     // S2Builder::GraphOptions::SiblingPairs::REQUIRE), but some were missing.
97     BUILDER_MISSING_EXPECTED_SIBLING_EDGES = 301,
98 
99     // S2Builder found an unexpected degenerate edge.  For example,
100     // Graph::GetLeftTurnMap() does not support degenerate edges.
101     BUILDER_UNEXPECTED_DEGENERATE_EDGE = 302,
102 
103     // S2Builder found a vertex with (indegree != outdegree), which means
104     // that the given edges cannot be assembled into loops.
105     BUILDER_EDGES_DO_NOT_FORM_LOOPS = 303,
106 
107     // The edges provided to S2Builder cannot be assembled into a polyline.
108     BUILDER_EDGES_DO_NOT_FORM_POLYLINE = 304,
109 
110     // There was an attempt to assemble a polygon from degenerate geometry
111     // without having specified a predicate to decide whether the output is
112     // the empty polygon (containing no points) or the full polygon
113     // (containing all points).
114     BUILDER_IS_FULL_PREDICATE_NOT_SPECIFIED = 305,
115   }
116 
117   // Set the error to the given code and printf-style message.  Note that you
118   // can prepend text to an existing error by calling Init() more than once:
119   //
120   //   error->Init(error->code(), "Loop %d: %s", j, error->text().c_str());
121   void initialize(T...)(Code code, string fmt, T args) {
122     _code = code;
123     _text ~= format(fmt, args);
124   }
125 
126   bool ok() const {
127     return _code == Code.OK;
128   }
129 
130   Code code() const {
131     return _code;
132   }
133 
134   string text() const {
135     return _text;
136   }
137 
138   // Clear the error to contain the OK code and no error message.
139   void clear() {
140     _code = Code.OK;
141     _text = "";
142   }
143 
144   string toString() const {
145     return _text;
146   }
147 
148 }