-
Notifications
You must be signed in to change notification settings - Fork 0
/
HPCVec2.cpp
executable file
·358 lines (310 loc) · 12.5 KB
/
HPCVec2.cpp
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
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//------------------------------------------------------------------------------
/// @file
/// @brief HPCVec2.hpp の実装
/// @author ハル研究所プログラミングコンテスト実行委員会
///
/// @copyright Copyright (c) 2014 HAL Laboratory, Inc.
/// @attention このファイルの利用は、同梱のREADMEにある
/// 利用条件に従ってください
//------------------------------------------------------------------------------
#include "HPCVec2.hpp"
#include "HPCCommon.hpp"
#include "HPCMath.hpp"
namespace hpc {
//------------------------------------------------------------------------------
/// 生成されたオブジェクトが、原点またはゼロベクトルを表すように
/// ゼロで初期化されたインスタンスを生成します。
Vec2::Vec2()
: x(0.0f)
, y(0.0f)
{
reset();
}
//------------------------------------------------------------------------------
/// x, y の各成分を定めてクラスのインスタンスを生成します。
///
/// @param[in] aX x成分の値
/// @param[in] aY y成分の値
Vec2::Vec2(float aX, float aY)
: x(aX)
, y(aY)
{
}
//------------------------------------------------------------------------------
/// 値を (0, 0) に初期化します。
void Vec2::reset()
{
x = 0.0f;
y = 0.0f;
}
//------------------------------------------------------------------------------
/// 現在の値がゼロベクトル(厳密)かどうかを返します。
///
/// @return x, y がそれぞれ厳密にゼロであれば @c true を返し
/// そうでなければ @c false を返します。
bool Vec2::isZero()const
{
return x == 0.0f && y == 0.0f;
}
//------------------------------------------------------------------------------
/// 引数に渡すベクトルと現在の値を比較し、誤差の範囲内で等しいかを返します。
///
/// @param[in] aVec 比較対象とするベクトル。
///
/// @return aVec の各要素が x, y と誤差の範囲で等しければ @c true を返し
/// そうでなければ @c false を返します。
bool Vec2::equals(const Vec2& aVec)const
{
return Math::IsEqual(x, aVec.x) && Math::IsEqual(y, aVec.y);
}
//------------------------------------------------------------------------------
/// 値の表す座標 (x, y) と引数 aPoint の表す座標間の距離を返します。
///
/// @param[in] aPoint 距離計算の目的地となる座標。
///
/// @return (x, y) と aPoint の距離。
float Vec2::dist(const Vec2& aPoint)const
{
return Math::Sqrt(squareDist(aPoint));
}
//------------------------------------------------------------------------------
/// 値の表す座標 (x, y) と引数の表す座標間の距離の二乗を返します。
///
/// @param[in] aPoint 距離計算の目的地となる座標。
///
/// @return (x, y) と aPoint の距離の二乗。
float Vec2::squareDist(const Vec2& aPoint)const
{
const float x2 = (aPoint.x - x) * (aPoint.x - x);
const float y2 = (aPoint.y - y) * (aPoint.y - y);
return x2 + y2;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) と 引数 aVec との内積を計算します。
///
/// @param[in] aVec 内積計算の対象となるベクトル。
///
/// @return (x, y) と aVec の内積。
float Vec2::dot(const Vec2& aVec)const
{
return x * aVec.x + y * aVec.y;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) と 引数 aVec との外積を計算します。
///
/// @param[in] aVec 外積計算の対象となるベクトル。
///
/// @return (x, y) と aVec の外積。
float Vec2::cross(const Vec2& aVec)const
{
return x * aVec.y - y * aVec.x;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) と引数 aVec の表すベクトルとの
/// なす角の余弦を求めます。
///
/// @param[in] aVec なす角を計算するためのベクトル。
///
/// @return (x, y) と aVec とのなす角 (ラジアン) の余弦 (cos)。
float Vec2::cos(const Vec2& aVec)const
{
const float d = dot(aVec);
const float l = length() * aVec.length();
HPC_LB_ASSERT_F(l, 0.0f);
return d / l;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) と引数 aVec の表すベクトルとの
/// なす角を求めます。
///
/// @param[in] aVec なす角を計算するためのベクトル。
///
/// @return (x, y) と aVec とのなす角の大きさ (ラジアン)。
float Vec2::angle(const Vec2& aVec)const
{
return Math::ACos(cos(aVec));
}
//------------------------------------------------------------------------------
/// 値の表すベクトルを aTarget と同じ方向に回転するとき、
/// その回転に必要な角度を、向きを含めて計算します。
/// 計算結果は angle に正負いずれかの符号がついたものになります。
///
/// @note 向きは反時計回りが正、時計回りが負を表します。
///
/// @param[in] aTarget 目標とする方向を表すベクトル。
///
/// @return 回転に必要な角度 (ラジアン) が [-π..π] の範囲で返されます。
float Vec2::rotSign(const Vec2& aTarget)const
{
const float d = dot(aTarget);
const float c = x * aTarget.y - y * aTarget.x;
return Math::ATan2(c, d);
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) の長さの二乗を計算します。
///
/// @return ベクトルの長さの二乗。
float Vec2::squareLength()const
{
return x * x + y * y;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) の長さを計算します。
///
/// @return ベクトルの長さ。
float Vec2::length()const
{
return Math::Sqrt(squareLength());
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) を指定の大きさに設定します。
///
/// @pre ベクトルがゼロベクトルではないことをあらかじめ確認する必要があります。
///
/// @param[in] aLength ベクトルの長さ。正の数を設定します。
void Vec2::normalize(float aLength)
{
HPC_LB_ASSERT_F(aLength, 0.0f);
*this /= length();
*this *= aLength;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) を指定の大きさに設定します。
///
/// @pre ベクトルがゼロベクトルではないことをあらかじめ確認する必要があります。
///
/// @param[in] aLength ベクトルの長さ。正の数を設定します。
///
/// @return (x, y) を aLength の長さに設定したベクトル。
Vec2 Vec2::getNormalized(float aLength)const
{
HPC_LB_ASSERT_F(aLength, 0.0f);
Vec2 aVec(*this);
aVec.normalize(aLength);
return aVec;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) を引数に与えられた角度方向に回転させます。
///
/// @param[in] aRad 回転角 (ラジアン)。反時計回りが正の値を表します。
void Vec2::rotate(float aRad)
{
const float rotatedX = Math::Cos(aRad) * x - Math::Sin(aRad) * y;
const float rotatedY = Math::Sin(aRad) * x + Math::Cos(aRad) * y;
x = rotatedX;
y = rotatedY;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) を引数に与えられた角度方向に回転させた
/// ベクトルを返します。
/// インスタンスの値自体は変更されません。
///
/// @param[in] aRad 回転角 (ラジアン)。反時計回りが正の値を表します。
///
/// @return (x, y) を aRad だけ回転させて得られるベクトル。
Vec2 Vec2::getRotated(float aRad)const
{
Vec2 v(*this);
v.rotate(aRad);
return v;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) を引数に与えられたベクトルに射影します。
///
/// @param[in] aVec 射影対象。求めたベクトルはこのベクトルと平行になります。
void Vec2::project(const Vec2& aVec)
{
const float l = aVec.length();
if (l == 0.0f) {
HPC_SHOULD_NOT_REACH_HERE();
return;
}
const float len = this->dot(aVec) / l;
Vec2 result = aVec.getNormalized() * len;
x = result.x;
y = result.y;
}
//------------------------------------------------------------------------------
/// 値の表すベクトル (x, y) を引数に与えられたベクトルに射影した
/// ベクトルを返します。
/// インスタンスの値自体は変更されません。
///
/// @param[in] aVec 射影対象。生成されるベクトルはこのベクトルと平行になります。
///
/// @return (x, y) を aVec に射影したベクトル。
Vec2 Vec2::getProjected(const Vec2& aVec)const
{
Vec2 v(*this);
v.project(aVec);
return v;
}
//------------------------------------------------------------------------------
bool Vec2::operator==(const Vec2& aRhs)const
{
return x == aRhs.x && y == aRhs.y;
}
//------------------------------------------------------------------------------
Vec2 Vec2::operator-()const
{
return Vec2(-x, -y);
}
//------------------------------------------------------------------------------
Vec2& Vec2::operator+=(const Vec2& aRhs)
{
x += aRhs.x;
y += aRhs.y;
return *this;
}
//------------------------------------------------------------------------------
Vec2& Vec2::operator-=(const Vec2& aRhs)
{
return *this += (-aRhs);
}
//------------------------------------------------------------------------------
Vec2 Vec2::operator+(const Vec2& aRhs)const
{
Vec2 v(*this);
v += aRhs;
return v;
}
//------------------------------------------------------------------------------
Vec2 Vec2::operator-(const Vec2& aRhs)const
{
return *this + (-aRhs);
}
//------------------------------------------------------------------------------
Vec2& Vec2::operator*=(float aRhs)
{
x *= aRhs;
y *= aRhs;
return *this;
}
//------------------------------------------------------------------------------
Vec2& Vec2::operator/=(float aRhs)
{
x /= aRhs;
y /= aRhs;
return *this;
}
//------------------------------------------------------------------------------
Vec2 Vec2::operator*(float aRhs)const
{
Vec2 v(*this);
v *= aRhs;
return v;
}
//------------------------------------------------------------------------------
Vec2 Vec2::operator/(float aRhs)const
{
Vec2 v(*this);
v /= aRhs;
return v;
}
//------------------------------------------------------------------------------
Vec2 operator*(float aLhs, const Vec2& aRhs)
{
return aRhs * aLhs;
}
}
//------------------------------------------------------------------------------
// EOF