Skip to content

Conversation

@linoal
Copy link
Contributor

@linoal linoal commented Apr 15, 2025

実装内容

MeshCodeクラスは、今後MeshCodeクラスとStandardMapGridクラスに分かれることになります。
その準備として、両者に共通する親クラスであるGridCodeを作り、MeshCodeをGridCodeに移行しました。

レビュー前確認項目

  • 自動ビルド・テストが通っていること

マージ前確認項目

  • 自動ビルド・テストが通っていること
  • Squash and Mergeが選択されていること
  • (libcitygmlの変更がある場合)libcitygmlがmasterの最新版になっていること

動作確認

Unityに導入して普段通り範囲選択とインポートが動けばOKです。
Unity SDKのブランチはfeature/grid_codeです。

自動テストはWindowsとMacで通っていれば良いとし、Linuxで通すのは後にします(GitHub Actionsで使ってるLinuxバージョンが未対応になったため)。

Summary by CodeRabbit

Summary by CodeRabbit

  • 新機能

    • グリッドコード(GridCode)クラスと標準地図グリッド(StandardMapGrid)クラスを追加し、メッシュコードからグリッドコードへの統一的な管理・操作を実現しました。
    • C#ラッパーにGridCodeやNativeVectorGridCodeなどの新しい型・APIを追加し、グリッドコードの取得やフィルタリングが可能になりました。
  • 機能改善

    • データセットアクセサやGmlFile等のAPIがメッシュコードからグリッドコードベースの設計に刷新され、柔軟なグリッド指定・階層操作が可能になりました。
    • C/C++/C#間のグリッドコード操作の互換性・一貫性が向上しました。
  • 互換性変更

    • 既存の「MeshCode」関連のAPI・プロパティ・テストは全て「GridCode」へと名称・型が変更されました。
    • C#のMeshCode関連APIおよびNativeVectorMeshCodeクラスは削除されました。
  • バグ修正・その他

    • .gitignoreやCMakeLists.txtの微修正、テストコードのグリッドコード対応など細かな改善を行いました。

linoal added 8 commits April 8, 2025 14:02
gitignore

cmakelists.txt

gitignore

clangd

grid_code.h

standard map grid

GridCode::create

grid実装中

同上

ビルド通る

C++テスト通る

fix c wrapper

gmlfile::gridCode

同上

以降途中

移行中
filter移行中

filter_by_grid_coords

移行中

C#テストが通る
共通部分まとめ

不要なのを削除中

警告対処中

警告対処中

不要なもの削除

コード整理
# Conflicts:
#	include/plateau/dataset/gml_file.h
#	test/test_mesh_extractor.cpp
@coderabbitai
Copy link

coderabbitai bot commented Apr 15, 2025

## Walkthrough

この変更は、PLATEAUデータセットの「メッシュコード」関連機能を「グリッドコード」へ全面的にリファクタリングするものです。C++とC#両方のAPI、内部ロジック、テスト、Cラッパー、ビルド設定が対象です。新たに抽象クラス`GridCode`とその実装(`MeshCode`, `StandardMapGrid`, `InvalidGridCode`)が導入され、関連ユーティリティやCラッパーも追加されました。既存の`MeshCode`型やAPIは`GridCode`ベースへ置換され、テストやC#ラッパーもこれに追従しています。ビルド設定や`.gitignore`等の微調整も含まれます。

## Changes

| ファイル/パス | 変更概要 |
|---|---|
| `.clangd`, `CMakeLists.txt`, `src/dataset/CMakeLists.txt`, `src/c_wrapper/CMakeLists.txt`, `.gitignore`, `.idea/vcs.xml` | Clangd設定・CMakeビルド設定の追加・修正、エディタ設定のgitignore追加、VCSマッピングの削除 |
| `include/plateau/dataset/grid_code.h`, `include/plateau/dataset/invalid_grid_code.h`, `include/plateau/dataset/standard_map_grid.h`, `src/dataset/grid_code.cpp`, `src/dataset/standard_map_grid.cpp` | 新規抽象クラス`GridCode`とその実装(`InvalidGridCode`, `StandardMapGrid`)の追加 |
| `include/plateau/dataset/mesh_code.h`, `src/dataset/mesh_code.cpp` | `MeshCode``GridCode`継承に変更、APIを仮想化し、型安全性・多態性を向上 |
| `include/plateau/dataset/gml_file.h`, `src/dataset/gml_file.cpp` | `MeshCode`から`GridCode`への移行、API・内部実装変更 |
| `include/plateau/dataset/i_dataset_accessor.h`, `src/dataset/local_dataset_accessor.h`, `src/dataset/local_dataset_accessor.cpp`, `src/dataset/server_dataset_accessor.h`, `src/dataset/server_dataset_accessor.cpp` | `MeshCode``GridCode`へ全面置換、フィルタ・取得APIなどの型・命名変更 |
| `src/dataset/grid_code_utils.h`, `src/dataset/grid_code_utils.cpp` | グリッドコード階層展開ユーティリティの新規追加 |
| `include/plateau/network/client.h`, `src/network/client.cpp` | `mesh_code``grid_code`へのリネーム |
| `src/c_wrapper/mesh_code_c.cpp`, `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorMeshCode.cs` | `MeshCode` Cラッパー・C#ラッパーの削除 |
| `src/c_wrapper/grid_code_c.cpp`, `src/c_wrapper/gml_file_c.cpp`, `src/c_wrapper/i_dataset_accessor_c.cpp`, `src/c_wrapper/vector_c.cpp` | `GridCode` Cラッパー新規実装、既存Cラッパーの`GridCode`対応・APIリネーム・型変更 |
| `test/test_dataset.cpp`, `test/test_dataset_source.cpp`, `test/test_mesh_extractor.cpp`, `test/test_server_dataset_accessor.cpp` | テストコードを`MeshCode``GridCode`へ修正、テストロジックの追従 |
| `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs`, `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorGridCode.cs` | C#での`GridCode`ラッパークラス新規追加 |
| `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/PInvokeDisposable.cs` | `autoDispose`制御フィールドの追加、リソース管理改善 |
| `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/DatasetAccessor.cs`, `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs` | `MeshCode`関連APIを`GridCode`へリネーム・型変更 |
| `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/MeshCode.cs` | `IsValid`, `Extent`, `Parse`などのプロパティ・メソッド削除 |
| `wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/*` | C#テストコードを`GridCode`へ全面置換、アサーション・テストロジックの追従 |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
  participant User
  participant CSharpAPI as C# API
  participant NativeAPI as C/C++ API
  participant GridCode
  participant MeshCode
  participant StandardMapGrid

  User->>CSharpAPI: GridCode.Create("53394525")
  CSharpAPI->>NativeAPI: plateau_grid_code_parse("53394525")
  NativeAPI->>GridCode: GridCode::createRaw("53394525")
  GridCode-->>MeshCode: new MeshCode("53394525")
  MeshCode-->>NativeAPI: MeshCode*
  NativeAPI-->>CSharpAPI: GridCode pointer
  CSharpAPI-->>User: GridCode instance

  User->>CSharpAPI: gridCode.Extent
  CSharpAPI->>NativeAPI: plateau_grid_code_get_extent(ptr)
  NativeAPI->>GridCode: getExtent()
  GridCode-->>NativeAPI: Extent
  NativeAPI-->>CSharpAPI: Extent
  CSharpAPI-->>User: Extent

Poem

うさぎ跳ねるよ、コードの森で
メッシュの名残、グリッドに変身!
新しいクラスに心が弾む
階層も拡張、型も多様
テストも一緒にぴょんぴょん進化
これからも広がるPLATEAUの地図
みんなでグリッド、ぴょんとジャンプ!

 ∩_∩
(・×・)< GridCodeばんざい!


<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡💬 Agentic Chat (Pro Plan, General Availability)</summary>
> 
> - We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b64d5f7f0af0583347ee9ef6d6353f761d21d42a and 5ad9adb9a8d7c96d7643995bb3d6ce3f2265e383.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `src/dataset/server_dataset_accessor.cpp` (4 hunks)
* `src/dataset/server_dataset_accessor.h` (3 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* src/dataset/server_dataset_accessor.cpp
* src/dataset/server_dataset_accessor.h

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: build-and-test (macos-14, arm64)
* GitHub Check: build-and-test (windows-2022, x86_64)

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Synesthesias/libplateau&utm_content=270):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🔭 Outside diff range comments (4)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/DatasetAccessor.cs (3)

77-90: 🛠️ Refactor suggestion

メソッド命名の不一致

FilterByGridCoordsという名前は他の部分と命名規則が一致していません。C++側ではfilterByGridCodesとなっており、プロパティ名もGridCodesです。一貫性を持たせるためにFilterByGridCodesに変更することを検討してください。

-        public DatasetAccessor FilterByGridCoords(IEnumerable<GridCode> gridCodes)
+        public DatasetAccessor FilterByGridCodes(IEnumerable<GridCode> gridCodes)

85-89: 🛠️ Refactor suggestion

変数名の不一致(続き)

nativeMeshCodesという変数名の使用が続いています。GridCodeへの移行に合わせてnativeGridCodesに更新するべきです。

             var result = NativeMethods.plateau_i_dataset_accessor_filter_by_grid_codes(
-                Handle, nativeMeshCodes.Handle, out var filteredPtr);
+                Handle, nativeGridCodes.Handle, out var filteredPtr);
             DLLUtil.CheckDllError(result);
-            nativeMeshCodes.Dispose();
+            nativeGridCodes.Dispose();

11-17: 🛠️ Refactor suggestion

コメントの更新が必要

クラスのドキュメントコメント内の「メッシュコード」という記述が残っています。GridCodeへの移行に合わせて「グリッドコード」に更新するべきです。

    /// <summary>
-    /// GMLファイル群から利用可能なファイル、メッシュコード、LODを検索します。
+    /// GMLファイル群から利用可能なファイル、グリッドコード、LODを検索します。
    /// C++の内部ではこれは基底クラスとなっており、継承によりローカル向けとサーバー向けの両方に対応しています。
    /// このクラスのポインタ (Handle) の具体的な型がローカル向けとサーバー向けのどちらであるかは、
    /// <see cref="DatasetSource"/> の初期化時に指定し、
    /// <see cref="DatasetSource.Accessor"/> でその型である DatasetAccessor を取得します。 
    /// </summary>
src/dataset/local_dataset_accessor.cpp (1)

284-295: 🛠️ Refactor suggestion

中心座標計算時の無効コード対策
grid_codes_ 内に無効なコードが含まれている場合、getExtent() が正しく機能しない恐れがあります。メッシュコードの除外またはエラー処理を行い、正確な中心座標を保証できるようにすることをおすすめします。

🧹 Nitpick comments (40)
src/dataset/grid_code_utils.h (1)

1-17: コードは明確で使いやすい関数シグネチャになっています

この新しいユーティリティ関数は、GridCodeの階層構造を処理するためによく設計されています。関数の目的と振る舞いが日本語のドキュメントコメントで十分に説明されています。

ただ、一点だけ改善提案があります:

 namespace plateau::dataset::utils {

     std::set<std::string> createExpandedGridCodeSet(const std::vector<GridCode*>& grid_codes);

-} 
+} // namespace plateau::dataset::utils
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/MeshCode.cs (1)

24-25: 不要な空白行を削除してください

この部分に追加された空白行は必要ないようです。コードの可読性を向上させるため、削除することを提案します。

-        
-        
src/dataset/grid_code_utils.cpp (1)

30-30: 不要な空白行を削除してください

この空白行は必要ないようです。コードの可読性を向上させるため、削除することを提案します。

-
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/PInvokeDisposable.cs (1)

15-15: autoDisposeの追加は有用な機能強化です

ネイティブリソースの寿命管理の柔軟性を高める良い変更です。これにより、GridCodeのようなラッパークラスでネイティブポインタを共有または転送する際のリソース管理が容易になります。

ただし、以下の点について検討してください:

  1. PreventAutoDisposeメソッドに対応するEnableAutoDisposeメソッドの追加を検討する
  2. このメソッドがいつ、なぜ使用されるべきかを説明するドキュメントを追加する
+        /// <summary>
+        /// 自動的なリソース廃棄を防止します。これは共有リソースや転送されるリソースに対して使用されます。
+        /// </summary>
         public void PreventAutoDispose()
         {
             this.autoDispose = false;
         }
+        
+        /// <summary>
+        /// 自動的なリソース廃棄を再有効化します。
+        /// </summary>
+        public void EnableAutoDispose()
+        {
+            this.autoDispose = true;
+        }

Also applies to: 19-23, 27-28, 34-37

test/test_dataset.cpp (2)

76-77: テスト名と実装内容が一致していません

テスト関数名はgetAllMeshCodesのままですが、実装はgrid_codesに変更されています。一貫性のために関数名もgetAllGridCodesに変更することを検討してください。


180-195: 名前空間のコメントを更新してください

無名名前空間のコメントは「テスト filterByGridCodes で使う」と更新されていますが、関数名doResultOfFilterByMeshCodesContainsMeshCodeはそのままです。関数名もdoResultOfFilterByGridCodesContainsGridCodeに変更することを検討してください。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetAccessorTest.cs (3)

33-36: 変数名の不一致があります

変数名はmeshCodesのままですが、プロパティはGridCodesに変更されています。変数名もgridCodesに更新すると一貫性が高まります。


175-175: FilterByGridCoordsという異なるメソッド名が使用されています

他の場所ではfilterByGridCodesという命名が使われていますが、ここではFilterByGridCoordsという異なる名前が使用されています。命名の一貫性を確保するため、FilterByGridCodesに統一することを検討してください。


180-186: 変数名の一貫性を確保してください

meshCodeという変数名が使われていますが、gridCodeに変更するとコードの意図がより明確になります。

src/dataset/grid_code.cpp (1)

10-38: グリッドコード生成のファクトリーメソッドが適切に実装されています

createRawメソッドは入力文字列のパターンに基づいて適切なグリッドコードタイプを生成します:

  • 空の文字列の場合はInvalidGridCode
  • 数字のみの場合はMeshCode
  • 数字と大文字英字の場合はStandardMapGrid
  • 例外発生時や上記以外のパターンの場合はInvalidGridCode

文字列解析と例外処理の実装は堅牢で、様々な入力パターンに対応できます。

ただし、lower case(小文字)の英字を含むケースや特殊文字を含むケースの扱いを明示的にすると、より堅牢になります。

-        // コードの文字を検査
+        // コードの文字を検査(数字と大文字英字の有無をチェック)
         for (char c : code) {
             if (std::isdigit(c)) has_digit = true;
             if (std::isupper(c)) has_upper = true;
+            // 無効な文字(特殊文字等)がある場合は早期リターン
+            if (!std::isalnum(c)) {
+                return new InvalidGridCode();
+            }
         }
include/plateau/dataset/invalid_grid_code.h (1)

51-57: メモリリークの可能性について

upperRaw()メソッドは new で生成したオブジェクトを返していますが、呼び出し側でこのメモリを適切に解放する必要があります。一般的に、戻り値で生ポインタを返すAPIは所有権の移譲を明示する必要があります。

親クラスの設計に合わせた実装でしょうが、コメントに「呼び出し側が解放責任を持つ」という注意書きを追加するか、スマートポインタを利用することを検討してください。

include/plateau/dataset/mesh_code.h (1)

81-81: 演算子オーバーロードの見直し

<演算子のオーバーロードが削除されているようです。これはおそらく新しいGridCodeComparator構造体によって比較機能が提供されるためと思われます。ただし、==演算子は残っています。一貫性のためには、比較操作をすべてGridCodeComparatorに移すことも検討してください。

src/c_wrapper/grid_code_c.cpp (1)

20-30: plateau_grid_code_get_extentでは引数チェックが適切に実装されています

引数のNULLチェックと例外ハンドリングが実装されており、堅牢なエラー処理ができています。ただし、extentパラメータのNULLチェックも追加するとより完全です。

以下の修正を提案します:

LIBPLATEAU_C_EXPORT APIResult LIBPLATEAU_C_API plateau_grid_code_get_extent(
    const GridCode* grid_code, Extent* extent
) {
    API_TRY{
        if (grid_code == nullptr) return APIResult::ErrorInvalidArgument;
+        if (extent == nullptr) return APIResult::ErrorInvalidArgument;
        *extent = grid_code->getExtent();
        return APIResult::Success;
    }
    API_CATCH;
    return APIResult::ErrorUnknown;
}
include/plateau/dataset/standard_map_grid.h (1)

58-60: 比較演算子のオーバーロードに注意が必要です

operator<のオーバーロードが非const参照版とconst参照版の2つ定義されています。これは意図的なオーバーロードだと思われますが、通常は一つの定義で十分です。また、他の比較演算子(!=, >, >=, <=)が実装されていないため、将来的には<=> (三方比較演算子)の使用を検討するか、他の比較演算子も実装することを推奨します。

C++20が使用可能な場合は、三方比較演算子(<=>)の使用を検討してください。または、非constバージョンのoperator<は不要かもしれません:

bool operator==(const StandardMapGrid& other) const;
-bool operator<(StandardMapGrid& other) const;
bool operator<(const StandardMapGrid& other) const;
src/dataset/mesh_code.cpp (5)

256-260: upperRaw() を直接 std::shared_ptr でラップする実装への考察
upper() 内で upperRaw() の生ポインタを std::shared_ptr<GridCode> に変換しています。この実装自体は正常に動作しますが、同じクラス内で生ポインタとスマートポインタを混在させると所有権管理が複雑になる場合があります。将来的には upperRaw() を排し、直接 std::make_shared<MeshCode>(*this) のような形にするなど、一貫した方法を検討ください。


310-312: isLargestLevel() のネーミングと判定条件の整合性
レベル2が最も大まかなメッシュとして定義されているようですが、「largest」という名前はレベル番号が小さい方を「大きいレベル」と呼ぶ概念と直感が逆になりやすいです。コードの可読性向上のため、この関数名についてコメントを追記するなど、混乱を防ぐ工夫を検討してください。


314-316: isSmallerThanNormalGml() の命名・実装意図の明確化
レベル4以上を「より小さい区域」とみなしてtrueを返す仕様ですが、「小さい区域 ≒ 細かいメッシュ」である点をクラスやメソッドのコメントで補足すると、読み手にとって分かりやすくなります。


318-320: isNormalGmlLevel() がレベル3を指す根拠を注記してください
レベル3が一般的なGMLファイルの標準レベルと位置付けられているようですが、その背景をソースコード上で簡潔に示すと保守や利用者の理解が容易になります。


322-324: 文字列比較による等価演算子の注意点
内部プロパティが異なっても最終的な文字列表現が同じなら等価と見なされます。現在のメッシュコード設計では問題ないかもしれませんが、将来的に異なるコードが同一文字列を生成する可能性がある場合は再度検討が必要です。

src/dataset/local_dataset_accessor.cpp (7)

9-10: GridCode関連ヘッダの追加インクルード
"plateau/dataset/grid_code.h""grid_code_utils.h" が新たに導入されています。今後の保守を考慮し、重複インクルードが生じていないか、不要なインクルードがないか再度ご確認ください。


15-15: using namespace utils; の利用範囲
広域的な using namespace は名前衝突リスクや可読性低下を招く可能性があります。限定的なスコープや明示的な名前空間指定に変更することを検討ください。


160-163: files_by_code_ への挿入処理の最適化
キーの存在確認(count())後に emplace() を呼んでいますが、C++17 以降の try_emplace() などで一度の操作で同等の処理を行える可能性があります。リファクタリングを検討ください。


200-202: コード文字列の比較方式
grid_codes_str_set.find(code) による比較は、大小文字・全角半角の問題などが発生しない前提で行われています。コード形式が厳格に数字のみなどであれば問題はないですが、フォーマットに多様性がある場合は追加検討が必要です。


211-218: shared_ptr から生ポインタへの変換設計
メソッド内で grid_code.get() を複数収集している点は、一時的な利用なら問題ありませんが、ライフサイクルの境界を超えて参照する場合に危険が生じます。現状では呼び出し直後にフィルタリングを完了するため、安全に機能していると考えられます。


304-315: getGridCodes() 内でのコード再生成によるパフォーマンス影響
ファイルから取得した GridCode を再度 GridCode::create(...) で生成し直しています。大量のファイルを扱う際、不要なオブジェクト生成コストが増大する恐れがあるため、必要性を再検討ください。


323-328: マップ操作時のパターン簡略化
files_by_code_ へのエントリを作成する前に count() を呼び出すパターンが繰り返し登場しています。C++17 以降であれば try_emplace()operator[] の直接利用など、より簡潔に書く手段があるので検討してください。

🧰 Tools
🪛 Cppcheck (2.10-2)

[performance] 325-325: Searching before insertion is not necessary.

(stlFindInsert)

include/plateau/dataset/grid_code.h (2)

47-66: レベル判定メソッド群の可読性向上
isLargestLevel(), isSmallerThanNormalGml(), isNormalGmlLevel() などメッシュのレベルを判別するメソッドは、名前と処理内容がコードのドメイン知識に依存しています。利用者が混乱しないよう、ドキュメントコメントの追記を検討してはいかがでしょうか。


68-94: create / createRaw のファクトリ実装と GridCodeComparator
新たな派生クラスが増える場合、create / createRaw で判定ロジックが膨らむ可能性があります。将来的な拡張性を考慮して設計を見直すと保守しやすいです。また、GridCodeComparatornullptr 同士の比較にどう対処するか、場合によっては順序付けを行うほうが安全です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (4)

17-22: エラー処理の明示的なガイドラインを検討してください
NativeMethods.plateau_grid_code_parseがエラーを返した場合、DLLUtil.CheckDllError(result)で例外が投げられる仕様だと思われます。失敗時のリトライやユーザ通知など、明示的なハンドリング要件があるか確認すると良いでしょう。


24-28: CopyFrom のメモリ管理戦略をレビューしてください
IntPtrを一時的にGridCodeに変換後、新たにCreate()する戦略です。生成済みオブジェクトを再利用できないか、あるいは意図的に新規生成しているか設計意図を明文化すると保守性が高まります。


42-53: StringCodeの取得方法はパフォーマンスに問題ないか検討ください
ネイティブ文字列をDLLUtil.GetNativeStringByValueで都度取得していますが、頻繁に呼び出される場合に影響がないか留意してください。大きな影響がなければこのままでも問題ありません。


111-115: ThrowIfInvalid() の追加コンテキストをログ出力することを検討してください
デバッグ時にどのようなコードが無効だったかの情報が得られると、問題解析が容易になる可能性が高いです。例外メッセージにStringCodeを含むなどの工夫を検討いただければと思います。

src/dataset/standard_map_grid.cpp (4)

18-26: getExtent() の未実装部分に注釈を入れると保守性が向上します
// TODO: 図郭コードから緯度経度範囲を計算する実装 とコメントされていますが、いつ、誰が対応するか管理しやすいよう具体的なタスクIDやIssueを紐付けるとよいでしょう。


28-37: isWithin() の内包ロジックが未実装です
同じ型であるかどうかだけをチェックし、実際の包含判定は常にfalseを返しています。処理の複雑さ次第では、今の段階で一部でも実装を進めたほうがコード利用側の混乱を減らせるかもしれません。


43-51: upper() とupperRaw() が自己コピーを返す設計について
将来的にレベルを持たせるなど、MeshCodeのような実装を踏襲するのであれば、ここで仮実装のまま放置すると利便性を損なう恐れがあります。TODOコメント等で今後の方針を補足することを推奨します。


73-83: 演算子オーバーロードでoperator<(...)が2種類定義されています
両方とも本質的には同じ動作ですが、ひとつは非const参照を取り、もうひとつはconst参照を取る形です。この重複定義が本当に必要か、あるいは誰かが意図的に別の用途を想定しているのか確認しましょう。

src/c_wrapper/vector_c.cpp (2)

71-84: GET_BY_PTR および GET_BY_VALUE マクロの範囲チェックロジックを再確認
index >= handle->size()で範囲外を確認する実装は有効ですが、呼び出し側が不正なインデックスを渡してくるケースが多い場合、ログ出力やエラー詳細を返すなど、追加の処理を検討しても良いかもしれません。


85-100: CLEANUPマクロでのdelete呼び出しにおける例外安全性を検討
delete element;の実行で何らかの例外が起きる可能性は低いですが、念のため、多数要素を削除する運用で万一例外が発生する場合の対応が必要かどうか確認してもよいでしょう。またdelete nullptrは安全ですが、念のため要素がnullptrでないかチェックが必要かどうかも考慮ください。

src/dataset/server_dataset_accessor.cpp (2)

10-10: using namespace utils; のスコープに注意
.cpp ファイル内の名前空間指定は衝突リスクが低いため問題ありませんが、不要な場合や明示的に限定したい場合は、個別の using 宣言を検討してください。


64-70: 中心点計算での getGridCodes() 多重呼び出し
ループ処理とサイズ取得で複数回 getGridCodes() を呼んでいます。性能面が気になる場合は、一度だけ取得してローカル変数で保持する方法が考えられます。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06f338d and dc3eab4.

📒 Files selected for processing (45)
  • .clangd (1 hunks)
  • .gitignore (1 hunks)
  • .idea/vcs.xml (0 hunks)
  • CMakeLists.txt (2 hunks)
  • include/plateau/dataset/gml_file.h (2 hunks)
  • include/plateau/dataset/grid_code.h (1 hunks)
  • include/plateau/dataset/i_dataset_accessor.h (5 hunks)
  • include/plateau/dataset/invalid_grid_code.h (1 hunks)
  • include/plateau/dataset/mesh_code.h (3 hunks)
  • include/plateau/dataset/standard_map_grid.h (1 hunks)
  • include/plateau/network/client.h (2 hunks)
  • src/c_wrapper/CMakeLists.txt (1 hunks)
  • src/c_wrapper/gml_file_c.cpp (1 hunks)
  • src/c_wrapper/grid_code_c.cpp (1 hunks)
  • src/c_wrapper/i_dataset_accessor_c.cpp (3 hunks)
  • src/c_wrapper/mesh_code_c.cpp (0 hunks)
  • src/c_wrapper/vector_c.cpp (2 hunks)
  • src/dataset/CMakeLists.txt (1 hunks)
  • src/dataset/gml_file.cpp (3 hunks)
  • src/dataset/grid_code.cpp (1 hunks)
  • src/dataset/grid_code_utils.cpp (1 hunks)
  • src/dataset/grid_code_utils.h (1 hunks)
  • src/dataset/local_dataset_accessor.cpp (7 hunks)
  • src/dataset/local_dataset_accessor.h (3 hunks)
  • src/dataset/mesh_code.cpp (3 hunks)
  • src/dataset/server_dataset_accessor.cpp (4 hunks)
  • src/dataset/server_dataset_accessor.h (3 hunks)
  • src/dataset/standard_map_grid.cpp (1 hunks)
  • src/network/client.cpp (1 hunks)
  • test/test_dataset.cpp (2 hunks)
  • test/test_dataset_source.cpp (1 hunks)
  • test/test_mesh_extractor.cpp (2 hunks)
  • test/test_server_dataset_accessor.cpp (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetAccessorTest.cs (5 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetSourceTest.cs (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs (3 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/MeshCodeTest.cs (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/GeometryModel/MeshExtractorTests.cs (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/DatasetAccessor.cs (4 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs (2 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/MeshCode.cs (3 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorGridCode.cs (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorMeshCode.cs (0 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/PInvokeDisposable.cs (1 hunks)
💤 Files with no reviewable changes (3)
  • .idea/vcs.xml
  • src/c_wrapper/mesh_code_c.cpp
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorMeshCode.cs
🧰 Additional context used
🧬 Code Graph Analysis (11)
src/dataset/gml_file.cpp (2)
include/plateau/dataset/gml_file.h (2)
  • getGridCode (22-22)
  • getGridCodeRaw (23-23)
src/dataset/grid_code.cpp (4)
  • createRaw (10-38)
  • createRaw (10-10)
  • create (40-42)
  • create (40-40)
test/test_mesh_extractor.cpp (1)
include/plateau/dataset/grid_code.h (1)
  • create (75-75)
include/plateau/dataset/invalid_grid_code.h (2)
include/plateau/dataset/grid_code.h (2)
  • GridCode (17-85)
  • GridCode (19-19)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (5)
  • GridCode (11-182)
  • GridCode (13-15)
  • GridCode (17-22)
  • GridCode (24-28)
  • GridCode (94-99)
src/c_wrapper/grid_code_c.cpp (4)
include/plateau/dataset/grid_code.h (3)
  • createRaw (83-83)
  • GridCode (17-85)
  • GridCode (19-19)
src/dataset/grid_code.cpp (2)
  • createRaw (10-38)
  • createRaw (10-10)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorGridCode.cs (1)
  • GridCode (24-30)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (5)
  • GridCode (11-182)
  • GridCode (13-15)
  • GridCode (17-22)
  • GridCode (24-28)
  • GridCode (94-99)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorGridCode.cs (3)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (17)
  • GridCode (11-182)
  • GridCode (13-15)
  • GridCode (17-22)
  • GridCode (24-28)
  • GridCode (94-99)
  • NativeMethods (123-181)
  • DisposeNative (117-121)
  • DllImport (125-129)
  • DllImport (131-134)
  • DllImport (136-139)
  • DllImport (141-144)
  • DllImport (146-150)
  • DllImport (152-156)
  • DllImport (158-162)
  • DllImport (164-168)
  • DllImport (170-174)
  • DllImport (176-180)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Interop/DLLUtil.cs (2)
  • DLLUtil (25-363)
  • CheckDllError (213-223)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/PInvokeDisposable.cs (3)
  • ThrowIfDisposed (39-42)
  • PreventAutoDispose (34-37)
  • DisposeNative (17-17)
src/dataset/local_dataset_accessor.cpp (6)
include/plateau/dataset/grid_code.h (1)
  • create (75-75)
src/dataset/local_dataset_accessor.h (5)
  • create (81-81)
  • create (81-81)
  • filterByGridCodes (37-37)
  • filterByGridCodes (38-38)
  • getGridCodes (71-71)
src/dataset/grid_code.cpp (2)
  • create (40-42)
  • create (40-40)
src/dataset/gml_file.cpp (2)
  • getPackage (80-82)
  • getPackage (80-80)
src/dataset/server_dataset_accessor.cpp (6)
  • filterByGridCodes (112-129)
  • filterByGridCodes (112-113)
  • filterByGridCodes (131-141)
  • filterByGridCodes (132-132)
  • getGridCodes (23-34)
  • getGridCodes (23-23)
src/dataset/grid_code_utils.cpp (2)
  • createExpandedGridCodeSet (5-28)
  • createExpandedGridCodeSet (5-5)
src/c_wrapper/vector_c.cpp (6)
include/plateau/dataset/gml_file.h (3)
  • GmlFile (14-77)
  • GmlFile (16-16)
  • GmlFile (17-17)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs (4)
  • GmlFile (16-246)
  • GmlFile (20-23)
  • GmlFile (29-35)
  • GmlFile (128-143)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorGmlFile.cs (1)
  • GmlFile (21-27)
include/plateau/polygon_mesh/city_object_list.h (3)
  • CityObjectIndex (11-80)
  • CityObjectIndex (15-18)
  • CityObjectIndex (20-23)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorCityObjectIndex.cs (1)
  • CityObjectIndex (33-38)
wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorExtent.cs (1)
  • Extent (21-27)
test/test_dataset_source.cpp (4)
include/plateau/dataset/dataset_source.h (1)
  • createServer (34-34)
src/dataset/dataset_source.cpp (2)
  • createServer (15-21)
  • createServer (15-15)
include/plateau/network/client.h (1)
  • createClientForMockServer (58-58)
src/network/client.cpp (2)
  • createClientForMockServer (46-48)
  • createClientForMockServer (46-46)
src/dataset/server_dataset_accessor.cpp (4)
src/dataset/local_dataset_accessor.cpp (6)
  • getGridCodes (304-315)
  • getGridCodes (304-304)
  • filterByGridCodes (189-208)
  • filterByGridCodes (189-190)
  • filterByGridCodes (210-220)
  • filterByGridCodes (211-211)
src/dataset/server_dataset_accessor.h (5)
  • getGridCodes (21-21)
  • create (39-39)
  • create (39-39)
  • filterByGridCodes (36-36)
  • filterByGridCodes (37-37)
src/dataset/grid_code.cpp (2)
  • create (40-42)
  • create (40-40)
src/dataset/grid_code_utils.cpp (2)
  • createExpandedGridCodeSet (5-28)
  • createExpandedGridCodeSet (5-5)
src/dataset/standard_map_grid.cpp (3)
include/plateau/dataset/standard_map_grid.h (16)
  • StandardMapGrid (15-65)
  • StandardMapGrid (17-17)
  • StandardMapGrid (18-18)
  • get (23-23)
  • getExtent (28-28)
  • isValid (38-38)
  • isWithin (33-33)
  • other (58-58)
  • other (59-59)
  • other (60-60)
  • upper (43-43)
  • upperRaw (44-44)
  • getLevel (49-49)
  • isLargestLevel (54-54)
  • isSmallerThanNormalGml (55-55)
  • isNormalGmlLevel (56-56)
src/dataset/mesh_code.cpp (22)
  • get (272-300)
  • get (272-272)
  • getExtent (139-191)
  • getExtent (139-139)
  • isValid (306-308)
  • isValid (306-306)
  • isWithin (237-248)
  • isWithin (237-237)
  • other (322-324)
  • other (322-322)
  • upper (256-260)
  • upper (256-256)
  • upperRaw (262-270)
  • upperRaw (262-262)
  • getLevel (302-304)
  • getLevel (302-302)
  • isLargestLevel (310-312)
  • isLargestLevel (310-310)
  • isSmallerThanNormalGml (314-316)
  • isSmallerThanNormalGml (314-314)
  • isNormalGmlLevel (318-320)
  • isNormalGmlLevel (318-318)
src/dataset/gml_file.cpp (2)
  • isValid (111-113)
  • isValid (111-111)
src/dataset/mesh_code.cpp (3)
include/plateau/dataset/grid_code.h (8)
  • isWithin (34-34)
  • get (24-24)
  • upper (44-44)
  • upperRaw (45-45)
  • isLargestLevel (56-56)
  • getLevel (50-50)
  • isSmallerThanNormalGml (61-61)
  • isNormalGmlLevel (66-66)
include/plateau/dataset/mesh_code.h (9)
  • isWithin (54-54)
  • other (79-79)
  • get (24-24)
  • upper (64-64)
  • upperRaw (65-65)
  • isLargestLevel (75-75)
  • getLevel (29-29)
  • isSmallerThanNormalGml (76-76)
  • isNormalGmlLevel (77-77)
src/dataset/standard_map_grid.cpp (22)
  • isWithin (28-37)
  • isWithin (28-28)
  • other (73-75)
  • other (73-73)
  • other (77-79)
  • other (77-77)
  • other (81-83)
  • other (81-81)
  • get (14-16)
  • get (14-14)
  • upper (43-46)
  • upper (43-43)
  • upperRaw (48-51)
  • upperRaw (48-48)
  • isLargestLevel (58-61)
  • isLargestLevel (58-58)
  • getLevel (53-56)
  • getLevel (53-53)
  • isSmallerThanNormalGml (63-66)
  • isSmallerThanNormalGml (63-63)
  • isNormalGmlLevel (68-71)
  • isNormalGmlLevel (68-68)
🪛 Cppcheck (2.10-2)
src/dataset/local_dataset_accessor.cpp

[performance] 325-325: Searching before insertion is not necessary.

(stlFindInsert)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build-and-test (macos-14, arm64)
  • GitHub Check: build-and-test (windows-2022, x86_64)
🔇 Additional comments (97)
.gitignore (1)

24-27: エディタ設定ディレクトリのignore追加は適切です

.vscode.ideaの追加、およびコメントの一般化は、複数エディタ利用を考慮した良い対応です。
他のignoreパターンとの整合性も問題ありません。

src/c_wrapper/CMakeLists.txt (1)

35-35: ファイル名の変更が適切に反映されています

mesh_code_c.cpp から grid_code_c.cpp への変更が正しく行われています。これはPRの目的である「メッシュコードを親クラスのグリッドコードに移行」に合致しています。

src/network/client.cpp (1)

118-118: メンバ変数の変更が適切に行われています

JSON フィールド "code" の値を mesh_code から grid_code メンバに割り当てるように変更されています。これはPRの目的である「メッシュコードを親クラスのグリッドコードに移行」に沿った適切な変更です。

src/dataset/CMakeLists.txt (1)

7-11: 新しいソースファイルが適切に追加されています

grid_code.cppgrid_code_utils.cppstandard_map_grid.cpp の3つの新しいソースファイルが plateau ターゲットに追加されています。これらの追加はPRの目的である「新しい親クラス GridCode の作成と MeshCode の移行」に適合しており、適切です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/MeshCodeTest.cs (1)

13-13: APIの変更が適切に反映されています

MeshCode.Parse("53394525") から GridCode.Create("53394525") への変更が適切に行われています。テストクラス名は MeshCodeTest のままですが、内部の実装は新しい GridCode クラスを使用するように更新されています。これはPRの目的に沿った変更です。

test/test_server_dataset_accessor.cpp (1)

30-30: MeshCodeからGridCodeへの移行が適切に行われています

このテストケースでは、filterByMeshCodes({MeshCode("53392670")})からfilterByGridCodes({GridCode::create("53392670")})への変更が行われています。これは親クラスのGridCodeへの移行という全体的なリファクタリングに合致しています。ファクトリーメソッドcreateを使用してGridCodeインスタンスを生成する新しいパターンも適切です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/GeometryModel/MeshExtractorTests.cs (1)

82-82: MeshCodeからGridCodeへの移行が適切に行われています

C#ラッパーでもMeshCode.Parse(meshCodeStr).ExtentからGridCode.Create(meshCodeStr).Extentへの変更が行われています。C#の命名規則に従ってメソッド名がPascalCase(Create)になっており、適切です。C++とC#の間でAPIが一貫した形で更新されています。

.clangd (1)

1-7: 開発環境の設定ファイルの追加は適切です

Clang言語サーバー用の設定ファイルが追加されています。Windows環境でのコンパイルフラグを適切に設定しており、out/build/x64-Debug-Unityをコンパイルデータベースとして使用し、-fPICフラグを削除して--target=x86_64-pc-windows-msvcフラグを追加しています。これにより開発体験が向上し、コード補完や静的解析がより正確に機能するようになります。

include/plateau/network/client.h (2)

4-7: 必要なヘッダーファイルの追加は適切です

<map><memory><plateau/dataset/grid_code.h>、および"libplateau_api.h"のインクルードが追加されています。これらはリファクタリングに伴い必要となったものと思われます。特にgrid_code.hのインクルードは、従来のmesh_code.hに代わるものとして適切です。


25-25: データ構造のフィールド名変更が適切に行われています

DatasetFileItem構造体内のフィールド名がmesh_codeからgrid_codeに変更されています。これはMeshCodeからGridCodeへの移行という全体的なリファクタリングの一環であり、一貫性が保たれています。

CMakeLists.txt (1)

82-83: clangdのための静的解析設定の追加

CMAKE_EXPORT_COMPILE_COMMANDS ONの設定追加は、clangdなどの静的解析ツールがコードをより効果的に解析できるようにするための良い改善です。これによりcompile_commands.jsonが生成され、コード補完やリファクタリングなどの開発体験が向上します。この変更はビルド出力には影響せず、開発ワークフローのみを改善します。

test/test_mesh_extractor.cpp (2)

4-4: GridCodeヘッダーへの変更

mesh_code.hからgrid_code.hへのインクルード変更は、PRの目的である「MeshCodeを親クラスのGridCodeに移行」に合致しています。


193-193: GridCode::createファクトリーメソッドの使用

MeshCode(mesh_code_str).getExtent()からGridCode::create(mesh_code_str)->getExtent()への変更は適切です。この変更により、新しい抽象化されたGridCodeインターフェースを通じてメッシュコードの機能にアクセスできるようになりました。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetSourceTest.cs (2)

15-15: GridCodeへのプロパティ参照の更新

MeshCodeからGridCodeへのプロパティ参照の変更は、C++側の変更に合わせた適切な修正です。APIの一貫性が保たれています。


23-23: コレクションプロパティ名の更新

MeshCodesからGridCodesへのコレクションプロパティ名の変更は、新しいGridCode抽象化に合わせた適切な修正です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs (3)

35-35: GridCodeプロパティへの参照更新

info.MeshCode.ToString()からinfo.GridCode.ToString()への変更は適切です。この変更により、テストは新しいGridCode抽象化を使用するようになりました。


79-79: フィルタリングメソッドの更新

FilterByMeshCodesからFilterByGridCoordsへの変更と、MeshCode.ParseからGridCode.Createへの変更は、新しいGridCodeベースのAPIに合わせた適切な修正です。


90-90: フィルタリングメソッドの一貫した更新

FilterByMeshCodesからFilterByGridCoordsへの変更と、MeshCode.ParseからGridCode.Createへの変更は、APIの一貫性を保つための適切な修正です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/MeshCode.cs (1)

44-45: ThrowIfInvalidのコメントアウトについて確認が必要です

バリデーションチェックがコメントアウトされていますが、これらのチェックは親クラスのGridCodeに移行されたのでしょうか?無効なMeshCodeが検出されないとバグの原因になる可能性があります。

親クラスのGridCode実装で同等のバリデーションが実装されていることを確認してください。特にisValidプロパティが削除されているため、この検証は重要です。

Also applies to: 65-66, 71-72

src/dataset/grid_code_utils.cpp (1)

5-28: 実装は堅牢でエッジケースも適切に処理されています

この関数はGridCodeの階層構造を効果的に処理し、無効なポインタやコードを適切にスキップしています。特に:

  • 不正なポインタやコードのスキップ (8-10行目)
  • インスタンス生成の説明コメント (12-13行目)
  • 階層をたどる明確なループ処理 (19-25行目)
src/c_wrapper/gml_file_c.cpp (1)

46-49: DLL_VALUE_FUNCからDLL_PTR_FUNCへの変更は適切です

関数がMeshCodeからGridCodeへと変更され、値から生ポインタを返すようになったため、マクロもDLL_VALUE_FUNCからDLL_PTR_FUNCへと変更されています。これはC++とCの間のインターフェースとして適切な変更です。

test/test_dataset.cpp (2)

184-185: GridCodeのポインタ使用は適切です

MeshCodeからstd::shared_ptr<GridCode>への変更は適切です。ポリモーフィズムをサポートし、新しいGridCode階層に合わせた設計になっています。


189-189: ポインタ参照の記法が正確です

grid_code[0]->get()でポインタからメソッドを呼び出す記法に変更されており、適切です。

include/plateau/dataset/gml_file.h (2)

22-23: GridCodeへのインターフェース変更は適切です

getGridCode()getGridCodeRaw()の2つのメソッドを追加することで、shared_ptrと生ポインタの両方の選択肢を提供しています。特にgetGridCodeRaw()にはコメントで寿命管理の責任が明確にされており、APIの使用者に対する注意点も適切に記載されています。


66-66: メンバ変数の型が適切に更新されています

文字列からstd::shared_ptr<GridCode>への変更は、リファクタリングの目的に合致しています。これにより、MeshCodeだけでなく将来的に追加される様々なグリッドコード型をサポートできるようになります。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetAccessorTest.cs (2)

24-25: C#テストが適切に更新されています

MeshCodesからGridCodesへのプロパティ変更が反映されています。


168-170: 一時的な値の変更に関する説明が適切に記載されています

座標値の変更に関して「国土基本図の図郭を実装するまでの一時的な値」というコメントが追加されており、将来的に更新される可能性を明記している点が良いです。

test/test_dataset_source.cpp (3)

21-33: グリッドコードのチェックがより包括的になりました

テストが複数タイプのグリッドコード(国土基本図の図郭とメッシュコード)をチェックするように改善されました。これはリファクタリングの意図と一致しており、より堅牢なテストになっています。


39-40: サーバーアクセサーのテストもグリッドコードを使用するように適切に更新されています

getMeshCodes()からgetGridCodes()への変更とグリッドコード文字列の取得方法が正しく更新されています。


42-42: GMLファイルのグリッドコード検証も更新されています

getMeshCode()からgetGridCode()->get()への更新が適切に行われており、新しいクラス構造と一致しています。

src/dataset/gml_file.cpp (4)

49-51: 適切なグリッドコード取得メソッドが追加されています

getGridCode()メソッドはshared_ptrを返すことで、より安全なメモリ管理を提供しています。この実装は親クラスへの移行の一部として適切です。


112-112: 有効性チェックが更新されています

isValid()メソッドがgetGridCode()->isValid()を使用するように適切に更新されています。これによりGridCodeの抽象化が正しく活用されています。


136-136: ファイル名解析が更新されています

ファイル名からグリッドコードを作成する部分がGridCode::createを使用するように適切に更新されています。これによりファイル名のパターンに応じた適切なグリッドコードタイプが生成されるようになりました。


53-55:

Details

❓ Verification inconclusive

生ポインタを返すメソッドも実装されています

getGridCodeRaw()メソッドはGridCode::createRawを使用して新しいインスタンスを作成しています。これはC++側とCラッパー間の橋渡しとして必要ですが、所有権の問題に注意が必要です。


🌐 Web query:

C++でメモリリークを防ぐベストプラクティスは?

💡 Result:

C++でメモリリークを防ぐためには、いくつかのベストプラクティスを採用することが重要です。以下に主な対策と具体例を紹介します。

1. スマートポインタの活用

C++11以降では、std::unique_ptrstd::shared_ptr などのスマートポインタを使用することで、メモリの自動管理が可能になります。これにより、手動でのnewdeleteを避け、メモリリークの発生を防ぐことができます[1][5][6]。

  • 例:
#include <memory>

void Example() {
    auto resource = std::make_unique<int[]>(10); // std::unique_ptrを使った安全なメモリ管理
    // リソースはスコープ終了時に自動解放される
}

2. RAII (Resource Acquisition Is Initialization) 原則の適用

RAII原則を活用して、リソース管理をオブジェクトのライフサイクルに紐付ける設計をします。デストラクタを実装して、オブジェクトの破棄時にリソースを自動的に解放する仕組みを構築します[1][6]。

  • 例:
class Resource {
public:
    Resource() { /* リソース確保 */ }
    ~Resource() { /* リソース解放 */ }
};

3. メモリ解放の徹底

手動で動的メモリを管理する必要がある場合、必ず対応するdeletedelete[]を呼び出す習慣をつけます。また、解放後はポインタをnullptrに設定することで、ダングリングポインタを防ぎます[4][6]。

  • 例:
int* array = new int[100];
delete[] array; // 解放
array = nullptr; // nullptrを設定

4. メモリリーク検出ツールの活用

ValgrindやVisual Studioのメモリプロファイラなど、メモリリークを検出するツールを定期的に使用することで、潜在的な問題を早期に発見できます[1][6][9]。

5. 循環参照の回避

std::shared_ptrを使用する場合、オブジェクト間に循環参照が発生しないよう注意してください。循環参照はstd::weak_ptr を利用して防ぐことができます[9]。

  • 例:
#include <memory>
struct A;
struct B;

struct A {
    std::shared_ptr<B> b_ptr;
};

struct B {
    std::weak_ptr<A> a_ptr; // 循環参照を防ぐ
};

6. コードレビューと文書化

コードレビューを実施し、コードの記述漏れや設計上の問題を発見します。また、メモリ管理の設計意図をコメントやドキュメントに残すことで、他の開発者が適切に保守できる環境を整えます[2].

7. 例外安全なコード設計

例外が発生してもリソースが確実に解放されるように、スマートポインタを活用したり、例外処理の構造を適切に設計します[6].


これらのベストプラクティスを日常的に実践することで、メモリリークのリスクを大幅に低減し、プログラムの安定性とパフォーマンスを向上させることができます。

Citations:


注意: 生ポインタの返却とメモリ管理の確認をお願いします

getGridCodeRaw() メソッドは、GridCode::createRaw() を利用して新たなインスタンスを作成し、その生ポインタを返却しています。これは C++ と C のラッパー間でのブリッジとして設計されていますが、返却されたポインタの所有権とメモリ管理に関しては、呼び出し側で適切な解放がなされないとメモリリークのリスクがあります。

  • 推奨事項:
    • 呼び出し側でのメモリ解放責任を明確にするため、ドキュメントやコメントで所有権の取り扱いを記載してください。
    • C++ ではスマートポインタ(例:std::unique_ptr)や RAII を活用することで自動的なリソース管理が推奨されていますが、C との連携により生ポインタが必要な場合、その限界と対策を再確認してください。

引き続き、メモリリーク防止のためのベストプラクティスに基づき、設計の妥当性を確認いただくようお願いします。

src/dataset/grid_code.cpp (1)

40-42: 共有ポインタを返すファクトリーメソッドは簡潔で適切です

createメソッドはcreateRawの結果をshared_ptrでラップして返すシンプルな実装になっています。メモリ管理の観点から適切です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GmlFile.cs (4)

81-83: ドキュメントがグリッドコードに適切に更新されています

XMLドキュメントコメントがMeshCodeからGridCodeに正しく更新されています。


85-85: プロパティ名が適切に更新されています

MeshCodeプロパティからGridCodeプロパティへの改名が行われており、APIの一貫性が保たれています。


212-214: ネイティブメソッドの宣言が適切に更新されています

plateau_gml_file_get_grid_codeメソッドの宣言が、グリッドコードのポインタを返すように更新されています。


90-93:

Details

❓ Verification inconclusive

ネイティブメソッド呼び出しが更新されています

グリッドコードを取得するためのネイティブメソッド呼び出しがplateau_gml_file_get_grid_codeに更新され、戻り値をGridCode.CopyFromメソッドに渡して管理対象のインスタンスを作成しています。

このコードはGridCodeクラスのCopyFromメソッドに依存していますが、その実装を確認できませんでした。このメソッドがネイティブポインタからのディープコピーを作成し、適切にメモリ管理を行っていることを確認することが重要です。


🏁 Script executed:

#!/bin/bash
# GridCode.CopyFromメソッドの実装を確認
rg "public static GridCode CopyFrom" --type cs

Length of output: 178


ネイティブメソッド呼び出し更新の確認と実装内容の検証依頼

更新されたコードでは、グリッドコードを取得するネイティブメソッド呼び出しが plateau_gml_file_get_grid_code に変更され、その戻り値が GridCode.CopyFrom 経由で管理対象のインスタンスへ変換されています。
なお、GridCode.CopyFrom メソッドは wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs 内に実装されていることが確認できました。
引き続き、以下の点についてご確認ください:

  • CopyFrom メソッド内で、ネイティブポインタから正確なディープコピーが作成されているか
  • メモリ管理が適切に行われ、ポインタリーク等の問題がないか
src/dataset/local_dataset_accessor.h (3)

37-38: メソッド名とパラメータ型が適切に更新されています

MeshCodeからGridCodeへの移行に合わせて、filterByMeshCodesからfilterByGridCodesへとメソッド名が変更され、パラメータ型も適切に更新されています。両方のオーバーロードが正しく対応しており、一貫性が保たれています。


69-71: メソッドのコメントとシグネチャが適切に更新されています

コメントが「都市モデルデータが存在するGridCodeのリスト」に更新され、戻り値の型もstd::set<std::shared_ptr<GridCode>, GridCodeComparator>に適切に変更されています。これはGridCodeへの移行に合致しています。


87-87: メンバー変数の型が適切に更新されています

mesh_codes_からgrid_codes_へ変数名が変更され、型もstd::set<std::shared_ptr<GridCode>, GridCodeComparator>に適切に更新されています。これによりポリモーフィックなGridCodeの取り扱いが可能になります。

include/plateau/dataset/invalid_grid_code.h (1)

1-64: InvalidGridCodeクラスの実装は適切です

GridCodeの子クラスとして無効なグリッドコードを表現する新しいクラスの導入は適切です。各メソッドの実装は一貫性があり、無効な状態を適切に表現しています。

特に以下の点が良いと思います:

  • isValid()が常にfalseを返す
  • すべてのメソッドが無効状態を適切に表現する値を返す
  • upper()メソッドが新しいInvalidGridCodeインスタンスを返す
  • getLevel()が-1を返す(有効なレベルは通常非負整数)

ドキュメントも充実しており、クラスの意図が明確です。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/DatasetAccessor.cs (1)

44-54: プロパティ名が適切に更新されています

MeshCodesからGridCodesへとプロパティ名が変更され、内部実装もNativeVectorGridCodeplateau_i_dataset_accessor_get_grid_codesに適切に更新されています。

include/plateau/dataset/mesh_code.h (6)

8-8: 適切なヘッダーのインクルード

新しい親クラスGridCodeのヘッダーが適切にインクルードされています。


16-16: 適切な継承関係の設定

MeshCodeクラスがGridCodeを継承するよう適切に変更されています。public plateau::dataset::GridCodeという明示的な修飾子の使用も適切です。


24-70: メソッドのオーバーライド修飾子の追加

親クラスからの仮想メソッドに対してoverride修飾子が適切に追加されています。これにより、意図したオーバーライドであることが明確になり、将来的な親クラスの変更によるシグネチャの不一致を検出しやすくなります。


64-65: 上位グリッドコードの取得メソッドの更新

upper()メソッドの戻り値型がstd::shared_ptr<GridCode>に適切に変更され、さらに生ポインタを返すupperRaw()メソッドも追加されています。これによりポリモーフィックな利用が可能になります。


72-77: レベル関連の新しいメソッドの実装

親クラスから導入された新しい仮想メソッドisLargestLevel()isSmallerThanNormalGml()isNormalGmlLevel()が適切にオーバーライドされています。これらのメソッドはグリッドコードのレベルに関する一貫した問い合わせをサポートします。


54-54: isWithinメソッドの更新

isWithinメソッドのパラメータ型がconst MeshCode&からconst GridCode&に変更されています。これにより、異なる種類のグリッドコード間での包含関係チェックが可能になります。適切な変更です。

src/c_wrapper/i_dataset_accessor_c.cpp (2)

19-31: plateau_i_dataset_accessor_get_grid_codes関数でのGridCodeオブジェクトの生成と管理が適切に行われています

GridCodeオブジェクトの作成にGridCode::createRawを使用しており、コメントでも明記されている点が良いです。ここでは動的に確保されたGridCodeポインタが返されており、呼び出し側で適切に管理(最終的に削除)される必要があることを示しています。


44-51: MeshCodeからGridCodeへの変更が一貫して適用されています

元のfilterByMeshCodesからfilterByGridCodesへの変更が正しく実装されています。パラメータ型の変更(std::vector<GridCode*>*)とメソッド呼び出しの変更が整合性を保っています。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/NativeVectorGridCode.cs (6)

8-12: クラスの目的と注意点が明確に記述されています

コメントで「中身はVectorの廃棄時の削除する」という寿命管理の注意点が明記されており、ユーザーにとって重要な情報が提供されています。


24-30: Atメソッドでの寿命管理が適切に実装されています

GridCode.CopyFromを使用して新しいGridCodeインスタンスを作成し、コメントで「寿命管理のためコピーを渡します」と説明されています。これにより、ベクトルが破棄された後もGridCodeオブジェクトが安全に使用できます。


51-57: 二段階の解放プロセスが適切に実装されています

DisposeNative内で、最初にCleanupElementsを呼び出してベクタ内の各要素を削除した後、ベクタ自体を削除するという二段階のプロセスが実装されています。これはC++側のリソース管理と整合性があり、適切なパターンです。


59-68: CleanupElementsメソッドは独立して使える便利な機能です

ベクタ自体を削除せずに内部の要素だけを削除できる機能を公開しており、柔軟な使用パターンをサポートしています。コメントも明確で、期待される動作がよく説明されています。


70-99: NativeMethodsクラスのDllImport定義が適切に実装されています

各ネイティブメソッドのためのDllImport属性と引数が正しく定義されています。入力と出力のパラメータ指定([In]out)も適切です。


43-49:

Details

✅ Verification successful

Add メソッドでのオブジェクト管理に注意が必要です

PreventAutoDispose()を呼び出してGridCodeの自動廃棄を防止していますが、これはベクタ内のオブジェクトがベクタ自体と同じ寿命を持つことを意味します。このパターンは正しいですが、もし将来的にこのクラスの使用パターンが変わる場合は注意が必要です。


🏁 Script executed:

#!/bin/bash
# 他のNativeVectorクラスでも同様のパターンが使用されているか確認
rg -A 5 "PreventAutoDispose" --glob="*.cs" 

Length of output: 1300


Add メソッドのオブジェクト管理は現状問題なく意図した実装となっています

  • gridCode.PreventAutoDispose() は、GridCode オブジェクトの自動破棄を無効化し、ベクタと同じ寿命で管理するパターンですが、このパターンは他の NativeVector 関連クラス(例: PInvokeDisposable.cs)でも一貫して採用されていることが確認できました。
  • 将来的にこのクラスの使用パターンが変更される場合は、オブジェクトのライフサイクル管理に改めて注意する必要があります。
src/c_wrapper/grid_code_c.cpp (3)

32-37: boolean戻り値関数のマクロ使用が適切です

DLL_2_ARG_FUNCマクロを使用して、引数チェックと戻り値設定のロジックを整理しています。引数がNULLの場合は適切にfalseを設定してエラーを返しています。


38-40: 文字列取得関数のマクロ使用が適切です

DLL_STRING_VALUE_FUNCマクロを使用して文字列値を取得する関数を簡潔に定義しています。


68-79: plateau_grid_code_upper関数は適切に実装されています

引数チェックと例外ハンドリングが実装されており、GridCodeのupper階層取得が正しく実装されています。upperRaw()メソッドを使用して生ポインタを返すという実装も適切です。

include/plateau/dataset/standard_map_grid.h (4)

10-15: クラスの目的が明確に説明されています

「国土基本図図郭」を表すクラスの目的と提供する機能について、コメントで適切に説明されています。これにより、このクラスがどのように使用されるべきかが明確になります。


16-18: コンストラクタの実装が適切です

明示的なコンストラクタと、デフォルトコンストラクタの両方が提供されています。明示的なコンストラクタはstd::stringを値でキャプチャしており、これはC++11以降の推奨パターンに従っています。


43-44: 上位グリッドへのアクセス方法が二種類提供されています

std::shared_ptr<GridCode>を返すupper()と、生ポインタを返すupperRaw()の両方が実装されており、異なる使用シナリオに対応できます。これはメモリ管理の柔軟性を高めます。


62-65: メンバ変数の命名と型選択が適切です

code_is_valid_の命名はクラス内変数の命名規則に従っており、型もそれぞれの目的に適しています。また、is_valid_にデフォルト値を設定しているのも良い実践です。

src/dataset/mesh_code.cpp (1)

262-269: レベル1メッシュを無効化する実装の意図確認
new_mesh_code->level_ = std::max(1, level_ - 1); の処理によってレベル1が生成された際、is_valid_ = false に設定しています。1次メッシュを完全にサポートしない方針であれば問題ありませんが、将来的な対応予定などがある場合は仕様を確認のうえコメント補足を検討ください。

src/dataset/local_dataset_accessor.cpp (2)

189-190: 生ポインタ引数のフィルタリングメソッド
filterByGridCodes(const std::vector<GridCode*>&...) は生ポインタを扱うため、呼び出し側で必ず有効期間が保証されていることを明示するなどのケアが必要です。スマートポインタ版のメソッドを優先利用することも検討ください。


197-198: createExpandedGridCodeSet の意図確認
引数にとった全コードを上位に遡ってセットへ追加していますが、期待通りの範囲で拡張されるか検証をお願いします。予期せず不要な上位コードが混入する可能性や、異常入力コードが含まれる場合の対策なども考慮ください。

include/plateau/dataset/grid_code.h (1)

1-16: GridCode 抽象クラスの導入
地図の区画を表すコードを抽象化し、MeshCodeStandardMapGrid など複数の実装系を一括で扱えるように設計されている点は大変有用です。ドキュメントコメントも適切に書かれており、クラスの目的が分かりやすいです。

wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (3)

13-16: コンストラクタの可視性とオプション引数の妥当性を確認しましょう
このコンストラクタはprivateですが、Create等の静的メソッド経由でインスタンス生成するデザインになっています。意図した使用方法であれば問題ありません。一方、autoDisposeの既定値をtrueにすることで、使用者が負の影響を受けないか検討が必要です。


30-40: Extent プロパティ内の例外処理に不整合がないか確認しましょう
ThrowIfInvalid()を呼び出したあとに、再度ネイティブ呼び出しをしているため、無効なハンドルでも処理が継続される可能性は低いと思われます。ただ、万一ネイティブ側で別のエラーが発生した場合のハンドリング手段をどうするか検討が必要です。


117-121: DisposeNative() の例外処理を含めたライフサイクル管理を要検証
ネイティブポインタの削除時にエラーが出た場合、現在はDLLUtilが例外を投げるだけです。マネージド側での最終的なクリーンアップ手順や再試行が必要かどうか確認してください。

src/dataset/standard_map_grid.cpp (1)

68-71: isNormalGmlLevel() の常にtrue返却について
MeshCodeと仕様を合わせる場合、レベル3等特定条件でのみtrueにする設計が考えられます。早めに正しい条件を確定しないと、ダミー実装が広範囲に影響する可能性があります。

src/c_wrapper/vector_c.cpp (2)

33-40: マクロ分割により可読性が向上しています
PLATEAU_VECTOR_GET_BY_PTRPLATEAU_VECTOR_GET_BY_VALUEに分割され、用途別に定義されている点は保守面で有益です。利用箇所ごとの誤用を減らせる設計として評価できます。


102-109: grid_code 用のマクロ利用が適切か検証しましょう
PLATEAU_VECTOR_GET_BY_VALUE(grid_code, GridCode*) はポインタを値として取得していますが、実際には生ポインタの再ラップ等が発生する可能性があります。C#側での利用シナリオやメモリ寿命管理に齟齬がないか再点検してください。

src/dataset/server_dataset_accessor.cpp (7)

6-6: ヘッダーの追加が行われています
grid_code_utils.h をインクルードしており、GridCode 関連のユーティリティを使用するための適切な変更です。


20-20: サーバー情報再取得時のクリア
loadFromServer() の再呼び出し時に grid_codes_ をクリアする処理は、古いデータを残さず常に最新状態を保持するための正しいアプローチです。


23-33: getGridCodes() での遅延読み込み
grid_codes_ が空のときにのみ初期化する設計はパフォーマンス的に有効ですが、マルチスレッド環境で同時呼び出しが起こる場合は競合に注意してください。


112-113: filterByGridCodes(const std::vector<GridCode>&...) の実装*
インターフェース要件を満たす形で実装されており、特に問題ありません。


118-119: grid_codes を文字列セットに変換
createExpandedGridCodeSet を使用して上位コードも含めて文字列セットを生成する実装は正しく機能しそうです。


124-125: ファイルごとの一致判定ロジック
grid_codes_str_set.find(file.grid_code) による単純な判定は分かりやすく、追加処理も正常に行われています。


132-139: shared_ptr から raw ポインタへの変換
共有所有権は維持されますが、変換後に参照範囲が適切に管理されているか注意が必要です。現状のロジックでは問題ないように見えます。

include/plateau/dataset/i_dataset_accessor.h (9)

6-7: GridCode とメモリヘッダーのインクルード
GridCode 型とポインタ管理に必要なヘッダーの追加が適切に行われています。


19-19: explicit な UdxSubFolder コンストラクタ
暗黙の型変換を防止するために explicit を付与するのは妥当です。


30-30: explicit operator の追加
operator std::string&()operator std::string() に explicit を付けることで、不要な暗黙変換を防ぎコードの安全性が高まります。

Also applies to: 34-34


98-101: getGmlFiles のシグネチャ変更
PredefinedCityModelPackage を const でなくした変更は使用箇所を確認したうえで問題なければ許容範囲です。


118-119: ドキュメントコメントの表記変更
メッシュコードからグリッドコードへの移行を示す説明になっており、コメントの整合性が保たれています。


122-122: filterByGridCodes(const std::vector<GridCode>&...) の追加*
インターフェースとして、メッシュコードからグリッドコードへ切り替える設計反映が正常に行われています。


126-126: filterByGridCodes 用のコメント
パラメータに関する説明が簡潔であり、分かりやすいです。


129-130: shared_ptr 版 filterByGridCodes
複数形引数への変換オーバーロードが追加されており、利便性向上に寄与しています。


133-133: getGridCodes() の仕様
グリッドコードのセットを返すメソッドとして定義され、明確な役割分担を示しています。

Also applies to: 135-135

src/dataset/server_dataset_accessor.h (6)

21-21: getGridCodes() のオーバーライド
MeshCode から GridCode に切り替わったインターフェースが明確で、整合性があります。


22-22: getGmlFiles(package) のオーバーライド
引数の型定義を更新し、他メソッド群との整合を保っています。


23-23: getGmlFiles(package_flags, out_gml_files) のシグネチャ
複数フラグ指定を受け付ける仕様が維持され、問題ありません。


36-36: filterByGridCodes(const std::vector<GridCode>&...) のオーバーライド*
MeshCode から GridCode* への移行でインターフェース要件を満たしており、妥当な実装に見えます。


37-37: filterByGridCodes(const std::vector<std::shared_ptr>&...) のオーバーライド
shared_ptr を利用したバージョンも用意され、柔軟性が高い設計です。


46-46: grid_codes_ メンバの型変更
従来の MeshCode に代えて GridCode を保持する設計は、今回のリファクタリングの意図に沿っています。

Comment on lines 237 to 248
bool MeshCode::isWithin(const GridCode& other) const {
// 型チェック
const auto* other_mesh = dynamic_cast<const MeshCode*>(&other);
if (other_mesh == nullptr) {
return false; // 異なる型の場合は内包関係にないとみなす
}

if (get() == other_mesh->get())
return true;

return get().substr(0, 6) == other.get();
return get().substr(0, 6) == other_mesh->get();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

内包関係の定義時の部分文字列評価を再検討ください
get().substr(0, 6) == other_mesh->get() により、コード文字列の先頭6桁と他方の完全なコード文字列が一致するかどうかで内包関係を判定しています。レベル3以上でコードが6桁を超える場合、意図せず「包含」と判定される可能性がないかご確認ください。必要に応じて、両コードのレベル同士を比較するロジック等を加えて、真の内包条件を定義することを検討してください。

Comment on lines 17 to 45
class LIBPLATEAU_EXPORT GridCode {
public:
virtual ~GridCode() = default;

/**
* \brief コードを文字列として取得します。
*/
virtual std::string get() const = 0;

/**
* \brief コードが表す緯度経度範囲を取得します。
*/
virtual geometry::Extent getExtent() const = 0;

/**
* \brief このコードが他のコードに内包されるかどうかを計算します。
*/
virtual bool isWithin(const GridCode& other) const = 0;

/**
* \brief コードが適切な値かどうかを返します。
*/
virtual bool isValid() const = 0;

/**
* \brief 1段階上のレベルのグリッドコードに変換します。
*/
virtual std::shared_ptr<GridCode> upper() const = 0;
virtual GridCode* upperRaw() const = 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

upperRaw() の生ポインタ戻り値について
所有権の所在が不明確なため、生ポインタを返すと呼び出し元が誤って解放しなかったり、二重解放したりする恐れがあります。ライフサイクル管理を明確化するためにも、unique_ptr などのスマートポインタを返す設計を検討ください。

Comment on lines +90 to +99
/// <summary>
/// 1段階上のレベルのグリッドコードに変換します。
/// </summary>
/// <returns>1段階上のレベルのグリッドコードオブジェクト</returns>
public GridCode Upper()
{
var result = NativeMethods.plateau_grid_code_upper(Handle, out var upperGridCodePtr);
DLLUtil.CheckDllError(result);
return new GridCode(upperGridCodePtr);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Upper() が常に新規インスタンスを返す実装で問題ないか検討しましょう
一段階上のグリッドコードを返すメソッドとのことですが、現状では同一インスタンスに近い返却を行っています。将来的にレベル変更の実装を行う際、混乱を避けるためのコメントやTODOの追加をおすすめします。

Comment on lines +8 to +12
StandardMapGrid::StandardMapGrid(std::string code) : code_(std::move(code)), is_valid_(false) {
// コードの形式を検証
// TODO
is_valid_ = true;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

コンストラクタの妥当性チェックを追加検討しましょう
is_valid_がデフォルトでfalseとなり、最後にtrueに更新されていますが、将来的にコード形式の厳密な検証が追加される見込みかと思われます。コメントだけでなく、エラー時の例外発生やログへの出力方針も決めておくと良いでしょう。

Comment on lines +53 to +66
int StandardMapGrid::getLevel() const {
// 仮実装: 常に1を返す
return 1;
}

bool StandardMapGrid::isLargestLevel() const {
// 仮実装: 常にtrueを返す
return true;
}

bool StandardMapGrid::isSmallerThanNormalGml() const {
// 仮実装
return false;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

getLevel(), isLargestLevel(), isSmallerThanNormalGml() の固定値返却に注意
現在は全て仮定義で固定値を返すため、利用者が誤解を招く可能性があります。実装が不完全であることを周知するコメントや例外、またはTODO等を追加し、利用者が本番環境で誤用しないようにするとよいでしょう。

プルリク指摘対応中

プルリク指摘に対応中

isWithin削除

プルリク指摘修正
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/dataset/local_dataset_accessor.cpp (3)

179-179: GridCode::create(code) の戻り値に対する有効性チェックを推奨
GridCode::create が無効なコードを返した場合にも getExtent() を呼び出しています。万一無効なコードだった場合に備え、isValid() の確認を行うと安全です。

- if (extent_filter.intersects2D(GridCode::create(code)->getExtent())) {
+ auto tmp_grid_code = GridCode::create(code);
+ if (tmp_grid_code->isValid() && extent_filter.intersects2D(tmp_grid_code->getExtent())) {
    ...
}

303-314: getGridCodes() は参照返却により可変データを直接晒しています。
利用側で誤って直接操作すると、内部状態へ影響する恐れがあります。必要に応じて const 参照返却やコピー返却を検討してください。


317-323: 無効な grid_code 登録に関する考慮を提案します。
gml_file_info.getGridCode()->get() が空文字を返すなど、無効コードの場合に意図しないキーが作られる可能性があります。

+ auto code_ptr = gml_file_info.getGridCode();
+ if (!code_ptr->isValid()) {
+     return; // または continue;
+ }
  const auto grid_code = code_ptr->get();
  files_by_code_.try_emplace(grid_code, std::vector<GmlFile>());
  files_by_code_[grid_code].push_back(gml_file_info);
src/dataset/server_dataset_accessor.cpp (2)

24-35: getGridCodes() メソッドの参照返却について
ローカル実装と同様に、可変なメンバーを参照返却することで、利用側の操作による破壊的変更が生じるリスクがあります。


105-105: GridCode::create の無効コード対策を推奨
無効なコード文字列が混入している場合でも ->getExtent() を直接呼んでいるため、一時変数で isValid() を確認する実装をお勧めします。

- auto extent = GridCode::create(file.grid_code)->getExtent();
+ auto tmp_code = GridCode::create(file.grid_code);
+ if (!tmp_code->isValid()) continue;
+ auto extent = tmp_code->getExtent();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc3eab4 and 32ab4d3.

📒 Files selected for processing (20)
  • include/plateau/dataset/grid_code.h (1 hunks)
  • include/plateau/dataset/invalid_grid_code.h (1 hunks)
  • include/plateau/dataset/mesh_code.h (2 hunks)
  • include/plateau/dataset/standard_map_grid.h (1 hunks)
  • src/c_wrapper/grid_code_c.cpp (1 hunks)
  • src/dataset/grid_code.cpp (1 hunks)
  • src/dataset/grid_code_utils.cpp (1 hunks)
  • src/dataset/grid_code_utils.h (1 hunks)
  • src/dataset/local_dataset_accessor.cpp (6 hunks)
  • src/dataset/mesh_code.cpp (2 hunks)
  • src/dataset/server_dataset_accessor.cpp (3 hunks)
  • src/dataset/server_dataset_accessor.h (3 hunks)
  • src/dataset/standard_map_grid.cpp (1 hunks)
  • test/test_dataset.cpp (2 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetAccessorTest.cs (5 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs (3 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/DatasetAccessor.cs (5 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs (1 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/MeshCode.cs (2 hunks)
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/PInvokeDisposable.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
  • src/dataset/grid_code_utils.cpp
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/DatasetAccessorTest.cs
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU.Test/Dataset/GmlFileTest.cs
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/MeshCode.cs
  • src/dataset/grid_code.cpp
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Native/PInvokeDisposable.cs
  • src/dataset/grid_code_utils.h
  • test/test_dataset.cpp
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/DatasetAccessor.cs
  • src/dataset/mesh_code.cpp
  • src/c_wrapper/grid_code_c.cpp
  • include/plateau/dataset/invalid_grid_code.h
  • include/plateau/dataset/standard_map_grid.h
  • include/plateau/dataset/mesh_code.h
  • include/plateau/dataset/grid_code.h
  • wrappers/csharp/LibPLATEAU.NET/CSharpPLATEAU/Dataset/GridCode.cs
  • src/dataset/server_dataset_accessor.h
  • src/dataset/standard_map_grid.cpp
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/dataset/local_dataset_accessor.cpp (5)
src/dataset/grid_code.cpp (2)
  • create (43-45)
  • create (43-43)
src/dataset/local_dataset_accessor.h (6)
  • create (81-81)
  • create (81-81)
  • filterByGridCodes (37-37)
  • filterByGridCodes (38-38)
  • getGridCodes (71-71)
  • addFile (89-89)
src/dataset/gml_file.cpp (2)
  • getPackage (80-82)
  • getPackage (80-80)
src/dataset/server_dataset_accessor.cpp (8)
  • filterByGridCodes (113-130)
  • filterByGridCodes (113-114)
  • filterByGridCodes (132-142)
  • filterByGridCodes (133-133)
  • getGridCodes (24-35)
  • getGridCodes (24-24)
  • addFile (85-90)
  • addFile (85-85)
src/dataset/grid_code_utils.cpp (2)
  • createExpandedGridCodeSet (5-28)
  • createExpandedGridCodeSet (5-5)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-and-test (macos-14, arm64)
🔇 Additional comments (12)
src/dataset/local_dataset_accessor.cpp (5)

9-10: インクルードの追加を確認しました。
外部依存の更新が明確で、可読性を損ねる要素は見受けられません。


157-161: GridCode の有効性チェックに対応しました。
gml_file の有効性も含め、段階的に検証するロジックは前回の指摘を反映しており、問題ありません。


187-206: フィルタリングロジックは概ね良好です。
createExpandedGridCodeSet により、階層的なコード展開が簡潔に実装されています。大量のコードが想定される場合でも、ログが多すぎないか確認するとよいでしょう。


209-218: filterByGridCodes の共有ポインタ対応がシンプルです。
引数の共有ポインタから生ポインタ配列に変換し、既存の処理を再利用する方針は理解しやすいです。


293-293: ゼロ除算の可能性を検証してください。
grid_codes_ が空の場合に (double)grid_codes_.size() が 0 となり、結果的に lat_sum / 0 が発生し得ます。空ケースが発生する可能性を確認し、必要に応じて対処を検討ください。

src/dataset/server_dataset_accessor.cpp (7)

5-6: ヘッダーインクルードの追加を確認しました。
<utility> はムーブセマンティクスの利用を補うために適切です。


8-8: #include "grid_code_utils.h" の追加問題ありません。
依存関係が明示され、保守性が向上しています。


13-15: ムーブセマンティクスが適切に導入されました。
std::move によりリソースのムーブが明確で、余計なコピーを抑えられます。


21-21: grid_codes_ の再初期化が明確です。
loadFromServer() 呼び出しごとにコードをリフレッシュできるので、意図がわかりやすい実装です。


65-71: 空の grid_codes_ によるゼロ除算を懸念
getGridCodes().size() が 0 のケースを想定すると、lat_sum / 0 が起こり得ます。データが一件もない場合の扱いを検討してください。


113-130: フィルタリング処理の実装は良好です。
createExpandedGridCodeSet により階層コードを一括で展開しており、既存のコードベースとの整合性も保たれています。


133-142: 共有ポインタ版フィルターメソッドの実装も問題ありません。
生ポインタへの変換を挟む構造によって重複ロジックを回避しており、シンプルで保守しやすいです。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/dataset/server_dataset_accessor.cpp (1)

132-142: 共有ポインタを使用したfilterByGridCodesのオーバーロード

共有ポインタの使用とその変換処理は適切です。ただし、ドキュメンテーションをさらに追加することを推奨します。

 std::shared_ptr<IDatasetAccessor>
     ServerDatasetAccessor::filterByGridCodes(const std::vector<std::shared_ptr<GridCode>>& grid_codes) const {
     auto result = std::make_shared<ServerDatasetAccessor>(dataset_id_, client_);
+    // 共有ポインタから生ポインタへの変換。
+    // 生ポインタはfilterByGridCodes内でのみ使用され、
+    // 共有ポインタのライフタイム中のみ有効です。
     std::vector<GridCode*> raw_grid_codes;
     raw_grid_codes.reserve(grid_codes.size());
     for(const auto grid_code : grid_codes) {
         raw_grid_codes.push_back(grid_code.get());
     }
     filterByGridCodes(raw_grid_codes, *result);
     return result;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32ab4d3 and b64d5f7.

📒 Files selected for processing (3)
  • src/dataset/local_dataset_accessor.cpp (6 hunks)
  • src/dataset/server_dataset_accessor.cpp (4 hunks)
  • src/geometry/geo_reference.cpp (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/geometry/geo_reference.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/dataset/local_dataset_accessor.cpp
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build-and-test (macos-14, arm64)
  • GitHub Check: build-and-test (windows-2022, x86_64)
🔇 Additional comments (9)
src/dataset/server_dataset_accessor.cpp (9)

5-6: ヘッダー追加はGood

std::moveを使用するための<utility>ヘッダーの追加は適切です。


8-8: 新しいユーティリティヘッダーの追加

grid_code_utils.hの追加はGridCodeへの移行に必要で、適切です。


13-16: コンストラクタの改善

値渡しとstd::moveを使用した実装は、モダンC++の効率的なパラメータ渡しイディオムに沿っており、良い改善です。


21-21: メッシュコードからグリッドコードへの移行

mesh_codes_からgrid_codes_への変更は、プロジェクト全体の方針に沿っており適切です。


24-35: メソッド名と実装の更新

getMeshCodes()からgetGridCodes()へのリネームと実装は、グリッドコードの概念を正しく反映しています。無効なグリッドコードのスキップなどのエラー処理も適切です。遅延初期化の手法もパフォーマンス面で良い実装です。


65-71: calculateCenterPointメソッドの更新

メッシュコード参照からグリッドコード参照への変更が一貫して行われており、正しく実装されています。


86-87: addFileメソッドの更新

フォーマットが若干変更されましたが、機能的な変更はなく、適切です。


103-106: filterメソッドの更新

メッシュコードからグリッドコードへの参照変更は適切に行われています。無効なグリッドコードのチェックが追加されたことは良い改善です。


113-130: filterByGridCodesメソッドの実装

filterByMeshCodesからfilterByGridCodesへのリネームと実装更新は適切です。新しいユーティリティ関数createExpandedGridCodeSetを使用することで、コードが簡潔になっています。

Copy link
Contributor

@yhikishima yhikishima left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご対応ありがとうございます!LGTMです〜!

@linoal linoal changed the base branch from dev/v3 to dev/v4 April 17, 2025 02:22
@linoal linoal merged commit 0917ffb into dev/v4 Apr 17, 2025
3 of 5 checks passed
@linoal linoal deleted the feature/mesh_code_alt branch April 17, 2025 02:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants