1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
|
#pragma once
#include "point.h"
#include "size.h"
#include <util/generic/string.h>
#include <util/generic/yexception.h>
#include <util/string/cast.h>
#include <util/generic/maybe.h>
#include <algorithm>
namespace NGeo {
class TGeoWindow {
public:
TGeoWindow() noexcept
= default;
TGeoWindow(const TGeoPoint& center, const TSize& size) noexcept
: Center_(center)
, Size_(size)
{
CalcCorners();
}
TGeoWindow(const TGeoPoint& firstPoint, const TGeoPoint& secondPoint) noexcept
: LowerLeftCorner_{std::min(firstPoint.Lon(), secondPoint.Lon()),
std::min(firstPoint.Lat(), secondPoint.Lat())}
, UpperRightCorner_{std::max(firstPoint.Lon(), secondPoint.Lon()),
std::max(firstPoint.Lat(), secondPoint.Lat())}
{
CalcCenterAndSpan();
}
const TGeoPoint& GetCenter() const noexcept {
return Center_;
}
void SetCenter(const TGeoPoint& newCenter) {
Center_ = newCenter;
CalcCorners();
}
const TSize& GetSize() const noexcept {
return Size_;
}
void SetSize(const TSize& newSize) {
Size_ = newSize;
CalcCorners();
}
const TGeoPoint& GetLowerLeftCorner() const noexcept {
return LowerLeftCorner_;
}
const TGeoPoint& GetUpperRightCorner() const noexcept {
return UpperRightCorner_;
}
void swap(TGeoWindow& o) noexcept {
Center_.swap(o.Center_);
Size_.swap(o.Size_);
LowerLeftCorner_.swap(o.LowerLeftCorner_);
UpperRightCorner_.swap(o.UpperRightCorner_);
}
bool IsValid() const noexcept {
return Center_.IsValid() && Size_.IsValid();
}
bool Contains(const TGeoPoint&) const;
bool Contains(const TGeoWindow& w) const {
return Contains(w.LowerLeftCorner_) && Contains(w.UpperRightCorner_);
}
void Stretch(double multiplier) {
Size_.Stretch(multiplier);
CalcCorners();
}
void Inflate(double additionX, double additionY) {
Size_.Inflate(additionX * 2, additionY * 2);
CalcCorners();
}
void Inflate(double addition) {
Inflate(addition, addition);
}
bool operator!() const {
return !IsValid();
}
double Diameter() const;
double Area() const {
return Size_.GetHeight() * Size_.GetWidth();
}
double Distance(const TGeoWindow&) const;
double GetApproxDistance(const TPointLL& point) const;
/**
* try to parse TGeoWindow from center and span
* return parsed TGeoWindow on success, otherwise throw exception
*/
static TGeoWindow ParseFromLlAndSpn(TStringBuf llStr, TStringBuf spnStr, TStringBuf delimiter = TStringBuf(","));
/**
* try to parse TGeoWindow from two corners
* return parsed TGeoWindow on success, otherwise throw exception
*/
static TGeoWindow ParseFromCornersPoints(TStringBuf leftCornerStr, TStringBuf rightCornerStr, TStringBuf delimiter = TStringBuf(","));
/**
* try to parse TGeoWindow from center and span
* return TMaybe of parsed TGeoWindow on success, otherwise return empty TMaybe
*/
static TMaybe<TGeoWindow> TryParseFromLlAndSpn(TStringBuf llStr, TStringBuf spnStr, TStringBuf delimiter = TStringBuf(","));
/**
* try to parse TGeoWindow from two corners
* return TMaybe of parsed TGeoWindow on success, otherwise return empty TMaybe
*/
static TMaybe<TGeoWindow> TryParseFromCornersPoints(TStringBuf leftCornerStr, TStringBuf rightCornerStr, TStringBuf delimiter = TStringBuf(","));
private:
TGeoPoint Center_;
TSize Size_;
TGeoPoint LowerLeftCorner_;
TGeoPoint UpperRightCorner_;
void CalcCorners();
void CalcCenterAndSpan();
};
inline bool operator==(const TGeoWindow& lhs, const TGeoWindow& rhs) {
return lhs.GetCenter() == rhs.GetCenter() && lhs.GetSize() == rhs.GetSize();
}
inline bool operator!=(const TGeoWindow& p1, const TGeoWindow& p2) {
return !(p1 == p2);
}
/**
* \class TMercatorWindow
*
* Represents a window in EPSG:3395 projection
* (WGS 84 / World Mercator)
*/
class TMercatorWindow {
public:
TMercatorWindow() noexcept;
TMercatorWindow(const TMercatorPoint& center, const TSize& size) noexcept;
TMercatorWindow(const TMercatorPoint& firstPoint, const TMercatorPoint& secondPoint) noexcept;
const TMercatorPoint& GetCenter() const noexcept {
return Center_;
}
TSize GetHalfSize() const noexcept {
return {HalfWidth_, HalfHeight_};
}
TSize GetSize() const noexcept {
return {GetWidth(), GetHeight()};
}
double GetWidth() const noexcept {
return HalfWidth_ * 2;
}
double GetHeight() const noexcept {
return HalfHeight_ * 2;
}
TMercatorPoint GetLowerLeftCorner() const noexcept {
return TMercatorPoint{Center_.X() - HalfWidth_, Center_.Y() - HalfHeight_};
}
TMercatorPoint GetUpperRightCorner() const noexcept {
return TMercatorPoint{Center_.X() + HalfWidth_, Center_.Y() + HalfHeight_};
}
bool Contains(const TMercatorPoint& pt) const noexcept;
bool Contains(const TMercatorWindow& w) const {
return Contains(w.GetLowerLeftCorner()) && Contains(w.GetUpperRightCorner());
}
void Stretch(double multiplier) {
HalfWidth_ *= multiplier;
HalfHeight_ *= multiplier;
}
void Inflate(double additionX, double additionY) {
HalfWidth_ += additionX;
HalfHeight_ += additionY;
}
void Inflate(double addition) {
Inflate(addition, addition);
}
double Area() const {
return GetHeight() * GetWidth();
}
private:
bool IsDefined() const {
return Center_.IsDefined() && !std::isnan(HalfWidth_) && !std::isnan(HalfHeight_);
}
private:
TMercatorPoint Center_;
double HalfWidth_;
double HalfHeight_;
};
inline bool operator==(const TMercatorWindow& lhs, const TMercatorWindow& rhs) {
return lhs.GetCenter() == rhs.GetCenter() && lhs.GetHalfSize() == rhs.GetHalfSize();
}
inline bool operator!=(const TMercatorWindow& p1, const TMercatorWindow& p2) {
return !(p1 == p2);
}
/**
* Typedefs
* TODO(sobols@): remove
*/
using TWindowLL = TGeoWindow;
/**
* Conversion
*/
TMercatorWindow LLToMercator(const TGeoWindow&);
TGeoWindow MercatorToLL(const TMercatorWindow&);
/**
* Utility functions
*/
bool Contains(const TMaybe<TGeoWindow>& window, const TGeoPoint& point);
TMaybe<TGeoWindow> Union(const TMaybe<TGeoWindow>& lhs, const TMaybe<TGeoWindow>& rhs);
TGeoWindow Union(const TGeoWindow& lhs, const TGeoWindow& rhs);
TMaybe<TGeoWindow> Intersection(const TMaybe<TGeoWindow>& lhs, const TMaybe<TGeoWindow>& rhs);
TMaybe<TGeoWindow> Intersection(const TGeoWindow& lhs, const TGeoWindow& rhs);
bool Intersects(const TGeoWindow& lhs, const TGeoWindow& rhs);
bool Intersects(const TMaybe<TGeoWindow>& lhs, const TMaybe<TGeoWindow>& rhs);
} // namespace NGeo
template <>
inline void Out<NGeo::TGeoWindow>(IOutputStream& o, const NGeo::TGeoWindow& obj) {
o << '{' << obj.GetCenter() << ", " << obj.GetSize() << ", " << obj.GetLowerLeftCorner() << ", " << obj.GetUpperRightCorner() << "}";
}
|