11#include " plateau/dataset/standard_map_grid.h"
2+
3+ #include < algorithm>
4+
25#include " plateau/geometry/geo_coordinate.h"
36#include < cctype>
47#include < stdexcept>
8+ #include < plateau/geometry/geo_reference.h>
9+ #include < plateau/polygon_mesh/mesh_extract_options.h>
510
611namespace plateau ::dataset {
712
8- StandardMapGrid::StandardMapGrid (const std::string& code) : code_(code), is_valid_(false ) {
9- // コードの形式を検証
10- // TODO
11- is_valid_ = true ;
13+ enum class StandardMapGridLevel
14+ {
15+ Invalid = -1 ,
16+ Level50000 = 0 ,
17+ Level5000 = 1 ,
18+ Level2500 = 2 ,
19+ Level1000 = 3 ,
20+ Level500 = 4 ,
21+ };
22+
23+ namespace {
24+ constexpr int level5000_division_count = 10 ;
25+ constexpr int level2500_division_count = 2 ;
26+ constexpr int level1000_division_count = 5 ;
27+ constexpr int level500_division_count = 10 ;
28+
29+ // 1セルのサイズ
30+ constexpr double level50000_cell_width = 40000.0 ; // 40km
31+ constexpr double level50000_cell_height = 30000.0 ; // 30km
32+ constexpr int level50000_row_count = 20 ; // 縦方向の分割数
33+
34+ constexpr double level5000_cell_height = level50000_cell_height / level5000_division_count; // 3km
35+ constexpr double level5000_cell_width = level50000_cell_width / level5000_division_count; // 4km
36+
37+ constexpr double level2500_cell_height = level5000_cell_height / level2500_division_count; // 1.5km
38+ constexpr double level2500_cell_width = level5000_cell_width / level2500_division_count; // 2km
39+
40+ constexpr double level1000_cell_height = level5000_cell_height / level1000_division_count; // 600m
41+ constexpr double level1000_cell_width = level5000_cell_width / level1000_division_count; // 800m
42+
43+ constexpr double level500_cell_height = level5000_cell_height / level500_division_count; // 300m
44+ constexpr double level500_cell_width = level5000_cell_width / level500_division_count; // 400m
45+
46+ // 原点から端までのセル数
47+ constexpr double row_half_count = 10.0 ;
48+ constexpr double col_half_count = 4.0 ;
49+ }
50+
51+ /* *
52+ * 図郭コードの文字列からレベル(詳細度)を返します。
53+ */
54+ StandardMapGridLevel parseLevel (const std::string& code) {
55+
56+ if (code.size () == 4 ) {
57+ return StandardMapGridLevel::Level50000;
58+ }
59+ if (code.size () == 6 ) {
60+ return StandardMapGridLevel::Level5000;
61+ }
62+ if (code.size () == 7 ) {
63+ return StandardMapGridLevel::Level2500;
64+ }
65+ if (code.size () == 8 ) {
66+ // 末尾がアルファベットであれば1000
67+ if (std::isalpha (code.back ())) {
68+ return StandardMapGridLevel::Level1000;
69+ }
70+ // 末尾が数字であれば500
71+ else {
72+ return StandardMapGridLevel::Level500;
73+ }
74+ }
75+
76+ // サポート対象外
77+ return StandardMapGridLevel::Invalid;
78+ }
79+
80+ StandardMapGrid::StandardMapGrid (const std::string& code) : code_(code), is_valid_(true ) {
81+ // 図郭コードの文字列が数字とアルファベットからなることをチェックします。
82+ if (!std::all_of (code_.begin (), code_.end (), [](char c)
83+ {
84+ return std::isalnum (c);
85+ })) {
86+ is_valid_ = false ;
87+ return ;
88+ }
89+
90+ // 図郭コードのレベル(詳細度)をチェックします。
91+ level_ = parseLevel (code);
92+ if (level_ == StandardMapGridLevel::Invalid) {
93+ is_valid_ = false ;
94+ return ;
95+ }
96+
97+ // 原点設定
98+ coordinate_origin_ = std::stoi (code.substr (0 , 2 ));
99+
100+ // 図郭コードの行番号、列番号を取得します。
101+ first_row_ = code[2 ]; // 1文字目は行
102+ first_col_ = code[3 ]; // 2文字目は列
103+ if (level_ == StandardMapGridLevel::Level50000) {
104+ return ;
105+ }
106+
107+ second_row_ = std::stoi (code.substr (4 , 1 ));
108+ second_col_ = std::stoi (code.substr (5 , 1 ));
109+
110+ if (level_ == StandardMapGridLevel::Level5000) {
111+ return ;
112+ }
113+
114+ if (level_ == StandardMapGridLevel::Level2500) {
115+ // 2×2分割のインデックスを計算
116+ int third = std::stoi (code.substr (6 , 1 )); // 1-4
117+ third_row_ = (third - 1 ) / 2 ; // 0 or 1
118+ third_col_ = (third - 1 ) % 2 ; // 0 or 1
119+ return ;
120+ }
121+
122+ if (level_ == StandardMapGridLevel::Level1000) {
123+ third_row_ = std::stoi (code.substr (6 , 1 )); // 0-4
124+ third_col_ = code.substr (7 , 1 )[0 ] - ' A' ; // 0-4 (A-E)
125+ return ;
126+ }
127+
128+ // Level500
129+ third_row_ = std::stoi (code.substr (6 , 1 )); // 0-9
130+ third_col_ = std::stoi (code.substr (7 , 1 )); // 0-9
12131 }
13132
14133 std::string StandardMapGrid::get () const {
15134 return code_;
16135 }
17136
137+ std::pair<TVec3d, TVec3d> StandardMapGrid::calculateGridExtent () const {
138+ double min_x = 0.0 , min_y = 0.0 ;
139+ double max_x = 0.0 , max_y = 0.0 ;
140+
141+ // 親セルの位置に基づいて方向フラグを設定(スコープ外でも使用するため、ここで定義)
142+ bool is_x_right = false ;
143+ bool is_y_upper = false ;
144+
145+ // Level50000の計算
146+ {
147+ // 南北方向(行)のインデックス計算
148+ // A行から数えて何番目かを計算(0始まり)
149+ int row_index = first_row_ - ' A' ;
150+
151+ // 東西方向(列)のインデックス計算
152+ // A列から数えて何番目かを計算(0始まり)
153+ int col_index = first_col_ - ' A' ;
154+
155+ // 基準点からの距離を計算
156+ // 列(X座標): 原点から左右対称(左が負、右が正)
157+ min_x = (col_index - col_half_count) * level50000_cell_width;
158+ max_x = min_x + level50000_cell_width;
159+
160+ // 行(Y座標): 原点から上下対称(上が正、下が負)
161+ min_y = (row_half_count - row_index) * level50000_cell_height;
162+ max_y = min_y + level50000_cell_height;
163+
164+ // 親セルの位置に基づいて方向フラグを設定
165+ is_x_right = col_index >= col_half_count; // E列より右側
166+ is_y_upper = row_index <= row_half_count; // 中央より上側
167+ }
168+
169+ if (level_ == StandardMapGridLevel::Level50000) {
170+ return {TVec3d (min_x, min_y, 0 ), TVec3d (max_x, max_y, 0 )};
171+ }
172+
173+ // Level5000の計算
174+ calculateSubGridExtent (
175+ min_x, min_y, max_x, max_y,
176+ second_row_, second_col_,
177+ level5000_cell_width, level5000_cell_height,
178+ is_x_right, is_y_upper);
179+
180+ if (level_ == StandardMapGridLevel::Level5000) {
181+ return {TVec3d (min_x, min_y, 0 ), TVec3d (max_x, max_y, 0 )};
182+ }
183+
184+ if (level_ == StandardMapGridLevel::Level2500) {
185+ calculateSubGridExtent (
186+ min_x, min_y, max_x, max_y,
187+ third_row_, third_col_,
188+ level2500_cell_width, level2500_cell_height,
189+ is_x_right, is_y_upper);
190+ return {TVec3d (min_x, min_y, 0 ), TVec3d (max_x, max_y, 0 )};
191+ } else if (level_ == StandardMapGridLevel::Level1000) {
192+ calculateSubGridExtent (
193+ min_x, min_y, max_x, max_y,
194+ third_row_, third_col_,
195+ level1000_cell_width, level1000_cell_height,
196+ is_x_right, is_y_upper);
197+ return {TVec3d (min_x, min_y, 0 ), TVec3d (max_x, max_y, 0 )};
198+ } else { // Level500
199+ calculateSubGridExtent (
200+ min_x, min_y, max_x, max_y,
201+ third_row_, third_col_,
202+ level500_cell_width, level500_cell_height,
203+ is_x_right, is_y_upper);
204+ return {TVec3d (min_x, min_y, 0 ), TVec3d (max_x, max_y, 0 )};
205+ }
206+ }
207+
208+ void StandardMapGrid::calculateSubGridExtent (
209+ double & min_x, double & min_y,
210+ double & max_x, double & max_y,
211+ int row_index, int col_index,
212+ double cell_width, double cell_height,
213+ bool is_x_right, bool is_y_upper) const {
214+
215+ // X座標の計算
216+ // is_x_rightがtrueの場合、親セルの左端から右方向に移動
217+ // is_x_rightがfalseの場合、親セルの左端から左方向に移動
218+ min_x = min_x + (is_x_right ? col_index * cell_width : -col_index * cell_width);
219+ max_x = min_x + cell_width;
220+
221+ // Y座標の計算
222+ // is_y_upperがtrueの場合、親セルの下端から上方向に移動
223+ // is_y_upperがfalseの場合、親セルの下端から下方向に移動
224+ min_y = min_y + (is_y_upper ? row_index * cell_height : -row_index * cell_height);
225+ max_y = min_y + cell_height;
226+ }
227+
18228 geometry::Extent StandardMapGrid::getExtent () const {
19229 if (!isValid ()) {
20230 throw std::runtime_error (" Invalid standard map grid code." );
21231 }
232+
233+ const auto [planeMin, planeMax] = calculateGridExtent ();
234+
235+ // GeoReferenceを取得
236+ plateau::polygonMesh::MeshExtractOptions options;
237+ options.coordinate_zone_id = coordinate_origin_;
238+ const auto geo_reference = geometry::GeoReference (options.coordinate_zone_id , options.reference_point , options.unit_scale , options.mesh_axes );
239+
240+ // 平面直角座標系から緯度経度に変換
241+ const auto min_coordinate = geo_reference.unproject (planeMin);
242+ const auto max_coordinate = geo_reference.unproject (planeMax);
22243
23- // TODO: 図郭コードから緯度経度範囲を計算する実装を追加
24- // この実装は図郭コードの仕様に基づいて行う必要があります
25- return geometry::Extent (geometry::GeoCoordinate (0 , 0 , 0 ), geometry::GeoCoordinate (0 , 0 , 0 ));
244+ return geometry::Extent (min_coordinate, max_coordinate);
26245 }
27246
28247 bool StandardMapGrid::isWithin (const GridCode& other) const {
@@ -31,28 +250,34 @@ namespace plateau::dataset {
31250 // 同じ型の場合のみ比較
32251 const auto * other_grid = dynamic_cast <const StandardMapGrid*>(&other);
33252 if (other_grid == nullptr ) return false ;
34-
35- // TODO: 図郭の包含関係を判定する実装を追加
36- return false ;
253+
254+ if (code_ == other_grid->code_ ) {
255+ return true ;
256+ }
257+
258+ // Level50000の場合は先頭4文字、Level50000以外の場合は先頭6文字で比較
259+ const size_t compare_length = (level_ == StandardMapGridLevel::Level50000) ? 4 : 6 ;
260+ return code_.substr (0 , compare_length) == other_grid->code_ .substr (0 , compare_length);
37261 }
38262
39263 bool StandardMapGrid::isValid () const {
40264 return is_valid_;
41265 }
42266
43267 std::shared_ptr<GridCode> StandardMapGrid::upper () {
44- // 仮実装: 自分自身のコピーを返す
45- return std::make_shared<StandardMapGrid>(code_);
268+ // 1段階上のレベルの図郭コードに変換
269+ auto new_code = std::make_shared<StandardMapGrid>(code_);
270+ new_code->level_ = static_cast <StandardMapGridLevel>(static_cast <int >(level_) - 1 );
271+ new_code->is_valid_ = new_code->level_ >= StandardMapGridLevel::Level50000;
272+ return new_code;
46273 }
47274
48275 int StandardMapGrid::getLevel () const {
49- // 仮実装: 常に1を返す
50- return 1 ;
276+ return (int )level_;
51277 }
52278
53279 bool StandardMapGrid::isLargestLevel () const {
54- // 仮実装: 常にtrueを返す
55- return true ;
280+ return level_ == StandardMapGridLevel::Level50000;
56281 }
57282
58283 bool StandardMapGrid::operator ==(const StandardMapGrid& other) const {
0 commit comments