何度も成功してきた Shapefiles の変換を実行したところ、今回は TransformationException で停止してしまいます。部分的な出力はなく、どのレコードが問題を引き起こしたかも明確ではありません。原因は、数千の有効なフィーチャの中に埋もれた 1 つの無効な座標であることが多いです。本記事では、このエラーで Shapefile 変換が失敗する理由と、Aspose.GIS for .NET 26.6 で導入された OperationErrorCollector を使用して C# で修正する方法を解説します。変換を最後まで実行させ、すべての有効なフィーチャを保持し、注意が必要なレコードの正確なレポートを取得する方法を学べます。

基本的な変換コードだけが必要な場合は、C# で Shapefile を KML に変換 を参照してください。このガイドはそれを基にして、エラー処理に焦点を当てています。

Shapefile 変換で TransformationException がスローされる理由

ほとんどのターゲット形式は、特定の座標系での座標を期待します。たとえば KML は常に WGS 84 の経度と緯度を使用します。変換中に、Aspose.GIS はソース座標系からターゲット座標系へすべての座標を変換します。もし座標の変換ができない場合、ライブラリは TransformationException をスローし、変換は停止します。

最も一般的な原因は次のとおりです:

  • プレースホルダー「no data」値。 一部のツールはジオメトリを空にする代わりにセンチネル値を書き込みます。この記事のサンプルファイルには (-1.7976931348623157E+308, -1.7976931348623157E+308) という点が含まれており、これは double の最小値で、どの座標系でも変換できません。
  • 範囲外座標。 ソース座標系の有効領域を超える値で、データ入力ミスや単位変換ミスが原因になることが多いです。
  • データと一致しない .prj ファイル。 メートル単位の投影座標が度単位の地理座標として宣言されている場合、多くの値が有効範囲を大幅に超えてしまいます。
  • 破損したジオメトリレコード。 レガシーエクスポートや破損したファイルは、個々のレコードに無効な数値を含むことがあります。

すべての場合において、問題は通常、ほんの数件のレコードに限られますが、デフォルトの動作では変換全体が破棄されます。

この機能が重要な理由

最初の失敗で停止するのは安全ですが、実際のパイプラインではコストがかかります。1つの不正なレコードがあると、データを変換できるようになるまで手動でファイルをクリーンアップしなければならず、例外だけでは他に何件のレコードが影響を受けているかは分かりません。エラーコレクションを有効にすると、次のことが可能になります:

  • 有効なすべてのフィーチャを変換し、1つの不正なレコードでファイル全体を失うことを防ぎます。
  • スキップされた各フィーチャのインデックスと座標を記録し、元データを修復できるようにします。
  • 汚染された入力でもクラッシュせずに、無人バッチ変換とETLジョブを実行します。
  • ウェブサービスでユーザーがアップロードした Shapefile を受け入れ、データ問題をユーザーに報告します。

C# と Aspose.GIS を使用した Shapefile 変換失敗の修正方法

Aspose.GIS for .NET は、Shapefile、KML、GeoJSON、GML、File Geodatabase などの地理空間フォーマットを、他の GIS ソフトウェアをインストールせずに読み取り、書き込み、変換できるマネージド ライブラリです。エラー コレクションにはバージョン 26.6 以降が必要です。NuGet からパッケージをインストールします:

dotnet add package Aspose.GIS

または、Package Manager Console を使用してください:

Install-Package Aspose.GIS

このチュートリアルで使用される型は次のとおりです:

  • VectorLayer (Aspose.Gis): ベクトルレイヤーを開き、作成し、変換します。VectorLayer.Convert が変換を実行します。
  • ConversionOptions (Aspose.Gis): DestinationDriverOptionsDestinationSpatialReferenceSystem を含む変換設定を保持します。
  • KmlOptions (Aspose.Gis.Formats.Kml): KML ドライバーオプションです。DriverOptions から ErrorCollector プロパティを継承します。
  • OperationErrorCollector (Aspose.Gis.Operations): 復旧可能なエラーを格納します。ErrorsCountHasErrorsAddClear を公開します。
  • OperationErrorTransformationError (Aspose.Gis.Operations): 各エラーは MessageException を持ちます。TransformationError には FeatureIndexXYZ が追加されます。
  • TransformationException (Aspose.Gis.SpatialReferencing): 座標を変換できず、コレクターが添付されていない場合にスローされます。

Shapefile 変換中の TransformationException の修正方法

この修正は2つの部分からなります。まず、OperationErrorCollector を添付して、変換が失敗する代わりに無効なフィーチャをスキップするようにします。次に、収集されたレポートを使用して、ソースでそれらのレコードを修復または削除します。以下の手順は、Shapefile から KML への変換を例として使用しています。

1. 環境の準備

  1. .NET コンソール プロジェクトを作成し、Aspose.GIS 26.6+ NuGet パッケージを追加します。
  2. Shapefile とその companion ファイル(.shp.shx.dbf、および .prj)を 1 つのフォルダーにコピーします。この例では data/light-traffics.shp を使用します。
  3. 必要な名前空間を追加します:
using System;
using System.IO;
using Aspose.Gis;
using Aspose.Gis.Formats.Kml;
using Aspose.Gis.Operations;
using Aspose.Gis.SpatialReferencing;

2. OperationErrorCollector の作成

コレクタは変換中に発生したすべての回復可能なエラーを記録します。異なるファイルからのエラーが混在しないように、変換ごとに新しいインスタンスを作成してください。

// Records recoverable errors instead of throwing them.
var errors = new OperationErrorCollector();

3. ConversionOptions を使用してコレクターをアタッチ

コレクタを KmlOptions.ErrorCollector に割り当て、次に KML オプションを DestinationDriverOptions として渡します。DestinationSpatialReferenceSystem を WGS 84 に設定することは KML ではオプションですが、コード内で対象の座標系を明示的にします。

var options = new ConversionOptions
{
    // KML always uses WGS 84; stating it makes the reprojection explicit.
    DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84,
    DestinationDriverOptions = new KmlOptions
    {
        ErrorCollector = errors // Skip and record features that fail transformation.
    }
};

4. 変換を実行する

ソース パス、Shapefile ドライバー、宛先パス、KML ドライバー、および先ほど構成したオプションを指定して VectorLayer.Convert を呼び出します。

string sourcePath = Path.Combine("data", "light-traffics.shp");
string destinationPath = Path.Combine("output", "light-traffics.kml");
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));

VectorLayer.Convert(sourcePath, Drivers.Shapefile, destinationPath, Drivers.Kml, options);

機能を変換できない場合、KML ドライバーはエラーをコレクターに追加し、その機能をスキップして次のものに進みます。TransformationException はスローされません。

5. スキップされた機能を報告し、出力を検証する

通常通りに戻ってきても、スキップされたフィーチャがある可能性があるため、必ず後でコレクタを確認してください。各エラーを TransformationError にキャストして、フィーチャインデックスと失敗した座標を取得し、出力ファイルを開いて書き込まれたフィーチャの数を確認します。

if (errors.HasErrors)
{
    Console.WriteLine($"Skipped {errors.Count} feature(s):");

foreach (var error in errors.Errors)
    {
        if (error is TransformationError transformationError)
        {
            Console.WriteLine(
                $"  Feature #{transformationError.FeatureIndex} at " +
                $"({transformationError.X}, {transformationError.Y}, {transformationError.Z}): {error.Message}");
        }
        else
        {
            Console.WriteLine($"  {error.Message}");
        }
    }
}

using (var layer = VectorLayer.Open(destinationPath, Drivers.Kml))
{
    Console.WriteLine($"Features written to KML: {layer.Count}");
}

サンプルファイルでは、コレクタはプレースホルダー点に対して 1 つのエラーを記録し、残りのフィーチャ(少なくとも 444 件)は KML ファイルに書き込まれます。

このレポートのフィーチャインデックスと座標は修正を完了します。データクレンジングのワークフローでソースの Shapefile を開き、報告されたレコードを特定して、修正または削除してください。多くのレコードが妥当な値でも失敗する場合は、まず .prj ファイルを確認してください。座標系の不一致が原因である可能性が高いです。

6. 完全サンプルコード

以下の完全なコンソール アプリケーションは変換を2回実行します。最初の実行はデフォルト設定を使用し、TransformationException を再現します。2回目の実行では OperationErrorCollector を添付し、無効な機能をスキップしてレポートを出力します。

using System;
using System.IO;
using Aspose.Gis;
using Aspose.Gis.Formats.Kml;
using Aspose.Gis.Operations;
using Aspose.Gis.SpatialReferencing;

namespace ShapefileTransformationErrors
{
    internal class Program
    {
        private static void Main()
        {
            string sourcePath = Path.Combine("data", "light-traffics.shp");
            string outputFolder = "output";
            Directory.CreateDirectory(outputFolder);

// -----------------------------------------------------------------
            // Run 1: default behavior. The first failed transformation aborts
            // the whole conversion with a TransformationException.
            // -----------------------------------------------------------------
            string failFastPath = Path.Combine(outputFolder, "fail-fast.kml");
            try
            {
                VectorLayer.Convert(sourcePath, Drivers.Shapefile, failFastPath, Drivers.Kml);
                Console.WriteLine("Default conversion finished without transformation errors.");
            }
            catch (TransformationException ex)
            {
                Console.WriteLine($"Default conversion aborted: {ex.Message}");
                Console.WriteLine($"Failing coordinate: ({ex.X}, {ex.Y}, {ex.Z})");
            }

// -----------------------------------------------------------------
            // Run 2: error-tolerant conversion. Invalid features are skipped
            // and recorded in the collector; valid features are written.
            // -----------------------------------------------------------------
            string destinationPath = Path.Combine(outputFolder, "light-traffics.kml");

var errors = new OperationErrorCollector();
            var options = new ConversionOptions
            {
                DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84,
                DestinationDriverOptions = new KmlOptions
                {
                    ErrorCollector = errors
                }
            };

VectorLayer.Convert(sourcePath, Drivers.Shapefile, destinationPath, Drivers.Kml, options);

// Report every skipped feature so the source data can be repaired.
            if (errors.HasErrors)
            {
                Console.WriteLine($"Conversion completed with {errors.Count} skipped feature(s):");

foreach (var error in errors.Errors)
                {
                    if (error is TransformationError transformationError)
                    {
                        Console.WriteLine(
                            $"  Feature #{transformationError.FeatureIndex} at " +
                            $"({transformationError.X}, {transformationError.Y}, {transformationError.Z}): {error.Message}");
                    }
                    else
                    {
                        Console.WriteLine($"  {error.Message}");
                    }
                }
            }
            else
            {
                Console.WriteLine("Conversion completed with no errors.");
            }

// Verify the output file.
            using (var layer = VectorLayer.Open(destinationPath, Drivers.Kml))
            {
                Console.WriteLine($"Features written to KML: {layer.Count}");
            }
        }
    }
}

7. よくある落とし穴と回避方法

PitfallReasonFix
ErrorCollector or OperationErrorCollector does not compileどちらも Aspose.GIS for .NET 26.6 に追加されました。NuGet パッケージを 26.6 以降にアップグレードします。
The conversion still throws TransformationException宛先ドライバーオプションにコレクターが設定されていません。ConversionOptions.DestinationDriverOptions に割り当てられたドライバーオプションオブジェクトに ErrorCollector を設定します。
A “successful” conversion is missing featuresコレクターが例外を抑制するため、Convert は通常通り戻ります。各呼び出し後に errors.HasErrors を確認し、結果をログに記録します。
Treating skipped features as fixedコレクターは無効なレコードをスキップしますが、修復は行いません。報告されたフィーチャーインデックスと座標を使用して、ソースデータ内のレコードを修正または削除します。
Hundreds of features fail at once.prj ファイルが実際の座標と一致していない可能性があります。個々のレコードを調査する前に、ソースの座標系を確認してください。
Errors from several files appear in one report同じコレクターインスタンスが複数の変換で再利用されました。ファイルごとに新しい OperationErrorCollector を作成するか、実行間で Clear() を呼び出します。
File-lock errors on repeated runsVectorLayer.Open で開かれたレイヤーが解放されていませんでした。VectorLayer.Openusing ブロックでラップします。

無料ライセンスを取得する

Aspose.GIS の一時的な無料ライセンスは、Aspose の一時ライセンスページから取得できます: https://purchase.aspose.com/temporary-license/

無料の追加リソース

結論

Shapefile 変換中に発生する TransformationException は、通常、少数のレコードが変換できない座標を含んでいることを意味します。たとえばプレースホルダー値、範囲外の数値、または .prj ファイルと一致しないデータなどです。C# でこれを修正するには 2 つの手順が必要です。まず OperationErrorCollector を添付して Aspose.GIS for .NET が無効なフィーチャをスキップし、変換を完了できるようにします。次に、収集されたフィーチャインデックスと座標を使用して元データを修復します。その結果、ハードな失敗を実用的なデータ品質レポートに変換しつつ、常に有効な出力を提供し続けるパイプラインが実現します。

FAQs

  1. Shapefile を変換する際に TransformationException が発生するのはなぜですか?
    これは、座標をソース座標系からターゲット座標系へ変換できない場合に発生します。一般的な原因としては、プレースホルダーの「no data」値、座標系の有効範囲外の座標、実際のデータと一致しない .prj ファイル、そして破損したジオメトリレコードがあります。

  2. 座標を変換できない場合、デフォルトでは何が起こりますか?
    VectorLayer.ConvertTransformationException をスローし、変換は中止されます。バージョン 26.6 以降、この例外は失敗した座標の XYZ 値も公開します。

  3. Aspose.GIS for .NET のどのバージョンが OperationErrorCollector をサポートしていますか? OperationErrorCollectorDriverOptions.ErrorCollector プロパティは Aspose.GIS for .NET 26.6 で導入されました。以前のバージョンには含まれていません。

  4. OperationErrorCollector は無効な座標を修正しますか? いいえ。変換に失敗したフィーチャをスキップし、記録します。そのため、出力には有効なフィーチャのみが含まれます。報告されたフィーチャインデックスと座標を使用して、ソースデータ内の不正なレコードを修正または削除してください。

  5. KML 以外の出力形式でも OperationErrorCollector を使用できますか? ErrorCollector はベースの DriverOptions クラスで定義されているため、すべてのドライバーオプションクラスで利用できます。ドキュメント例は KML と MapInfo TAB の宛先をカバーしていますが、本番環境で使用する前に対象ドライバーで動作をテストしてください。

  6. 各収集されたエラーにはどのような詳細が含まれていますか? すべての OperationErrorMessage と基になる Exception を提供します。変換失敗は TransformationError オブジェクトとして報告され、失敗した座標の FeatureIndexXYZ の値が追加されます。

  7. 変換がエラーなしで完了したかどうかはどうやって確認できますか? VectorLayer.Convert が返された後、コレクターの HasErrors または Count プロパティを確認してください。例外がスローされずに完了した変換でも、スキップされたフィーチャーがある場合があります。

続きを読む