GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
math_polygon2.cpp
[詳解]
1
3
4// Copyright(c) 2023-2025 Design Engineering Laboratory, Saitama University
5// Released under the MIT license
6// https://opensource.org/licenses/mit-license.php
7
8#include "math_polygon2.h"
9
10#include "cassert_define.h"
11#include "math_util.h"
12
13
14namespace designlab
15{
16
17Polygon2::Polygon2(const std::vector<Vector2>& vertex)
18{
19 assert(vertex.size() <= kMaxVertexNum); // 頂点数は最大値を超えてはいけない.
20
21 for (int i = 0; i < static_cast<int>(vertex.size()); ++i)
22 {
23 AddVertex(vertex[i]);
24 }
25}
26
28{
29 for (int i = 0; i < vertex_num; i++)
30 {
31 if (vertex[static_cast<size_t>(i)] == v)
32 {
33 return false;
34 }
35 }
36
37 vertex[static_cast<size_t>(vertex_num)] = v;
38 ++vertex_num;
39
40 assert(vertex_num <= kMaxVertexNum); // 頂点数は最大値を超えてはいけない.
41
42 return true;
43}
44
45void Polygon2::RemoveVertex(const int i)
46{
47 if (i < 0 || i >= GetVertexNum())
48 {
49 return;
50 }
51
52 // i番目の頂点を削除する.そして,i+1番目以降の頂点をi番目以降にコピーする.
53 for (int j = i; j < GetVertexNum() - 1; ++j)
54 {
55 vertex[j] = vertex[j + 1];
56 }
57
58 vertex[vertex_num - 1] = Vector2(0.0f, 0.0f);
59
60 --vertex_num;
61}
62
64{
65 const int num = GetVertexNum();
66
67 // 早期リターン.頂点数が3未満の場合は多角形ではない.
68 if (num < 3)
69 {
70 return false;
71 }
72
73 // 右回りか左回りかを調べる.
74 const auto v1 = vertex[1] - vertex[0];
75 const auto v2 = vertex[2] - vertex[1];
76
77 bool is_left_turn = v1.Cross(v2) > 0.0f;
78
79 for (int i = 1; i < num; ++i)
80 {
81 const auto& v1_2 = vertex[(i + 1) % num] - vertex[i];
82 const auto& v2_2 = vertex[(i + 2) % num] - vertex[(i + 1) % num];
83
84 if (is_left_turn && v1_2.Cross(v2_2) < 0.0f)
85 {
86 return false;
87 }
88 else if (!is_left_turn && v1_2.Cross(v2_2) > 0.0f)
89 {
90 return false;
91 }
92 }
93
94 return true;
95}
96
97bool Polygon2::IsInside(const Vector2& point) const
98{
99 const int num = GetVertexNum();
100
101 // 早期リターン.頂点数が3未満の場合は多角形ではない.
102 if (num < 3)
103 {
104 return false;
105 }
106
107 int cnt = 0;
108
109 // 頂点が右回りか左回りかを調べる.
110 bool is_left_turn = (vertex[1] - vertex[0]).Cross(vertex[2] - vertex[1]) > 0.0f;
111
112 if (!is_left_turn)
113 {
114 for (int i = 0; i < num; ++i)
115 {
116 const auto& v1 = vertex[i] - point;
117 const auto& v2 = vertex[(i + 1) % num] - point;
118
119 if (v1.Cross(v2) == 0.0f && v1.Dot(v2) <= 0.0f)
120 {
121 return true; // 点が辺上にある.
122 }
123
124 if (v1.y < v2.y)
125 {
126 if (v1.y < 0.0f && 0.0f <= v2.y && v1.Cross(v2) > 0.0f)
127 {
128 --cnt;
129 }
130 }
131 else
132 {
133 if (v2.y < 0.0f && 0.0f <= v1.y && v1.Cross(v2) < 0.0f)
134 {
135 ++cnt;
136 }
137 }
138 }
139 }
140 else
141 {
142 for (int i = 0; i < num; ++i)
143 {
144 const auto& v1 = vertex[i] - point;
145 const auto& v2 = vertex[(i + 1) % num] - point;
146
147 if (v1.Cross(v2) == 0.0f && v1.Dot(v2) <= 0.0f)
148 {
149 return true; // 点が辺上にある.
150 }
151
152 if (v1.y > v2.y)
153 {
154 if (v2.y < 0.0f && 0.0f <= v1.y && v1.Cross(v2) < 0.0f)
155 {
156 --cnt;
157 }
158 }
159 else
160 {
161 if (v1.y < 0.0f && 0.0f <= v2.y && v1.Cross(v2) > 0.0f)
162 {
163 ++cnt;
164 }
165 }
166 }
167 }
168
169 return (cnt % 2 == 1);
170}
171
172std::string Polygon2::ToString() const
173{
174 std::string res;
175
176 res += "Vertex Num : " + std::to_string(GetVertexNum()) + "\n";
177
178 for (int i = 0; i < GetVertexNum(); ++i)
179 {
180 res += "Vertex " + std::to_string(i) + " : " +
181 GetVertex(i).ToString() + "\n";
182 }
183
184 res += "Max X : " + math_util::FloatingPointNumToString(GetMaxX()) + "\n";
185 res += "Min X : " + math_util::FloatingPointNumToString(GetMinX()) + "\n";
186 res += "Max Y : " + math_util::FloatingPointNumToString(GetMaxY()) + "\n";
187 res += "Min Y : " + math_util::FloatingPointNumToString(GetMinY()) + "\n";
188
189 res += "Convex :";
190 res += (IsConvex() ? "TRUE" : "FALSE");
191 res += "\n";
192
193 return res;
194}
195
196} // namespace designlab
std::string FloatingPointNumToString(const T num, const int digit=kDigit, const int width=kWidth)
小数を文字列に変換する関数. C++ では C のフォーマットのように %3.3f とかで小数を文字列に変換できないため自作する.
Definition math_util.h:161
constexpr float GetMaxX() const
頂点の中で最大のx座標を返す関数.
std::string ToString() const
多角形のデータを文字列で出力する
constexpr float GetMinY() const
頂点の中で最小のy座標を返す関数.
bool IsInside(const Vector2 &point) const
点が多角形の内部にあるかどうか調べる関数. 多角形が凸でない場合は正しく判定できない.
constexpr void AddVertex(const Vector2 &v)
頂点を追加する関数.
bool AddVertexCheckForDuplicates(const Vector2 &v)
頂点を追加する関数.他の頂点と重なっている場合は追加しない.
constexpr int GetVertexNum() const
多角形の頂点数を返す関数.
constexpr float GetMaxY() const
頂点の中で最大のy座標を返す関数.
void RemoveVertex(const int index)
頂点を削除する関数.遅いので多用するべきではない.
constexpr Vector2 GetVertex(const int i) const
頂点の座標を返す関数.
constexpr float GetMinX() const
頂点の中で最小のx座標を返す関数.
bool IsConvex() const
多角形が凸かどうか調べる関数.
2次元の位置ベクトルを表す構造体.
std::string ToString() const
このベクトルを文字列にして返す. (x, y) の形式,小数点以下3桁まで.