
座標変換エンジンをSwiftとC#で二重実装する — 結果一致の保証
GeoDiveExa(GDE)の座標変換ロジックは、もともとC#(.NET MAUI)で書かれたものでした。そこから精度検証を重ねて抽出したのがSwift Package「GeoCoreJP」で、GeoConverterPro(GCVP)・GeoPrism JP(GPRM)が共有しています。つまり同じ変換アルゴリズムが、今はSwiftとC#の2つの言語で並行実装されている状態です。1人開発でなぜこの二重管理を選んでいるのか、結果の一致をどう保証しているかをまとめます。
なぜ二重実装か — プラットフォーム戦略
GDEを含む.NET MAUI群と、GCVP・GPRMを含むSwift/Xcode群は、開発体制もターゲットも異なります。MAUI群は共同開発者と共有するリポジトリで、既存のRTK通信コードやWindows/Android展開の資産があるため、これらを活かすにはC#が現実的な選択です。一方、Swift/Xcode群はiOS専業のため、ネイティブなUI体験やApp Store配信の最適化を優先してSwiftを選んでいます。
「1つのエンジンをどちらか一方の言語に統一する」のではなく、プラットフォームごとに得意な言語で実装し、アルゴリズムの仕様だけを共通の正とするという方針を取っています。
移植の方針 — アルゴリズム仕様を正、コードは言語流儀で
二重実装で最初に決めたのは、「どちらのコードを正本とするか」ではなく、「変換アルゴリズムの仕様(測地系の定義・パラメータファイルの読み方・補正の適用順序など)を正とし、コードそのものはSwift・C#それぞれの言語流儀に従って書く」という方針です。
Swift版のクラス構造をそのままC#に直訳するのではなく、.NETらしい命名・例外処理・非同期パターンで書き直しています。逆にC#側の実装をSwiftへ持ち込む場合も同様です。コードの見た目が違っても、入力に対する出力が一致することだけを保証の対象にしています。
結果一致の検証 — 地理院検証値+相互比較テスト
一致の保証は、次の2段構えで行っています。
- 地理院公式ツールとの突き合わせ:GCVP側で使っているのと同じ検証用テストポイント(地震補正テスト・重複地震テスト・境界域テスト・47都道府県庁など)を、C#実装のテストケースとしても流用します。国土地理院の公式変換ツールが出す値との差を許容誤差内に収めることを、両言語で個別に確認します。
- Swift版とC#版の相互比較:同じ入力座標をSwift版とC#版それぞれに与え、出力を突き合わせます。地理院ツールとの単独比較だけでなく、自分たち同士の実装間で不一致が出ないかを継続的にチェックする、という二段階の検証です。
この相互比較テストがあることで、「地理院ツールとの差は許容誤差内だが、Swift版とC#版の間でだけ数mm〜数cmずれている」といった、片方の実装だけに潜むバグを見つけやすくなります。
言語差で出た罠 — 数値型・丸め・文字列変換
同じアルゴリズムでも、言語が変わると引っかかる場所が変わります。実際に遭遇した罠は次のようなものでした。
- 数値型の違い:SwiftのDoubleとC#のdoubleは基本的に同じIEEE 754倍精度ですが、標準ライブラリの三角関数・べき乗関数の実装が完全に同一とは限らず、極めて小さな丸め誤差が出る場面がある
- 丸めモードの違い:文字列⇄数値変換や表示用の丸め処理で、言語のデフォルト丸め規則(銀行丸めか四捨五入かなど)が異なり、表示桁の最後の1桁だけ食い違うことがある
- 文字列変換・カルチャ依存:C#では実行環境のカルチャ設定によって小数点の表記(
.と,)が変わりうるため、パラメータファイルのパースや出力フォーマットでは明示的に不変カルチャ(InvariantCulture)を指定する必要がある
いずれも「アルゴリズムのロジックは合っているのに、表示直前の変換で数値が化ける」というパターンで、相互比較テストがなければ発見が遅れていたと思われる罠です。
保守の現実 — 片方だけ直す事故を防ぐ
二重実装の一番の弱点は、パラメータ更新や不具合修正を、うっかり片方にしか反映し忘れることです。地殻変動補正パラメータの年次更新のように、両実装に同じ変更が必要な作業では、次のような運用でこの事故を防いでいます。
- 変更内容をアルゴリズム仕様側にまず書き出す(Swift・C#どちらのコードでもない、共通の記述として残す)
- Swift版を直したら、同じ変更をC#版にも反映したかをチェックリストで確認する
- 相互比較テストを変更のたびに実行し、意図しない差分が出ていないかを機械的に検出する
「正しく直す」よりも「片方だけ直して事故る」ことの方が起きやすいというのが実感で、最終的には相互比較テストという機械的なチェックに頼る運用に落ち着いています。
まとめ
- GeoCoreJPは、MAUI群(C#)とSwift/Xcode群という開発体制の違いから、SwiftとC#で並行実装されている。
- 「コードを統一する」のではなく「アルゴリズム仕様を正とし、コードは言語流儀で書く」という方針を採っている。
- 地理院公式ツールとの検証に加え、Swift版とC#版どうしの相互比較テストで、片方だけに潜むバグを検出している。
- 数値型・丸めモード・カルチャ依存の文字列変換など、言語差特有の罠がある。
- パラメータ更新のたびに「片方だけ直す事故」が起きやすく、相互比較テストによる機械的なチェックが保守の要になっている。
次回は、C#版GeoCoreJPのAPI設計について書く予定です。
関連記事
- GeoCoreJPの高精度座標変換を支える設計思想(GeoConverterPro)
- 共同開発リポと個人リポを分ける — 次期アプリ用リポジトリ新設の判断(GeoDiveExa)
- .NET MAUI アプリ3本を .NET 8 から .NET 10 へ移行した(GeoDiveExa)
- 全テストポイントを国土地理院の変換サイトと比較する(GeoConverterPro)
開発者より: アプリ・Kindle本・オープンソースの一覧は GitHub: amru195704 にまとめています。
お願い
本記事の情報は参考目的で掲載しており、正確性・完全性を保証するものではありません。誤記・不正確な情報がございましたら、コメント欄よりご指摘いただければ、確認のうえ修正いたします。

コメントを残す