[QGIS & Gdal]Geotiffファイルのピクセルサイズが一定でない? ~その1~

2020/9/15追記
GeoTiffファイルの原点を左上にしたら、きれいに表示されました。
後日に検証記事を書こうと思いますが、取り急ぎご報告まで。


250mメッシュ1)昭和48年7月12日行政管理庁告示第143号のデータをGeoTiffファイルにして地図を描いている時に気づいたこと。

「(QGISで表示させると)ピクセルの位置が本来の座標からずれる!?」

ということで、250mメッシュのGeoTiffファイルとその中心点の緯度経度の座標ファイルを作ってQGISで表示させてみました。

250mメッシュのGeoTiffと中心点

やっぱり合ってない。

よく見ると、所々にサイズがおかしいピクセルが。

サイズのおかしなピクセル(赤枠内)

とりあえず、メッシュデータなどのラスタファイルを拡大して表示する場合には注意が必要なようです。
つづき:[QGIS & Gdal]QGISにてGeotiffファイルのピクセルサイズが一定でない? ~その2~

ちなみに、GeoTiffファイルと座標ファイル(CSV)を作るプログラムはこんな感じ。

using System.IO;
using System.Security.Cryptography;
using GDAL = OSGeo.GDAL;

const string sOutCsv = @"C:\…\Mesh.csv";
const string sOutTif = @"C:\…\Mesh.tif";
const int iW = 40;
const int iH = 40;
const double dLon0 = 139d;
const double dLat0 = 35.5d;
const double dX = 11.25d / 3600d;
const double dY = 7.5d / 3600d;

static void Main(string[] args)
{
    Encoding sjis = Encoding.GetEncoding(932);
    InitGdal(); //GDALを初期化する(環境変数の設定など)

    double[] dV = new double[iH * iW];
    using(StreamWriter sw = new StreamWriter(sOutCsv, false, Encoding.GetEncoding(932)))
    {
        int i = 0;
        sw.WriteLine("Lon,Lat,Value");
        for (int iY = 0; iY < iH; iY++)
        {
            for (int iX = 0; iX < iW; iX++)
            {
                dV[i] = GetRandom();
                sw.WriteLine("{0},{1},{2}", dLon0 + dX / 2 + dX * iX, dLat0 + dY / 2 + dY * iY, dV[i]);
                i++;
            }
        }
    }

    GDAL.Driver drv = GDAL.Gdal.GetDriverByName("GTiff");
    
    //出力ファイル:ファイル名・幅・高さ・バンド数・ピクセルのデータ型、オプション(null)
    using (GDAL.Dataset dsOut = drv.Create(sOutTif, iW, iH, 1, GDAL.DataType.GDT_Float64, null))
    {
        //位置情報(Xmin, ΔX/px, 0, Ymax, 0, ΔY/px)
        double[] dGeo = new double[] { dLon0, dX, 0d, dLat0, 0, dY };
        dsOut.SetGeoTransform(dGeo);

        using (GDAL.Band bd = dsOut.GetRasterBand(1))
        {
            //データ書き込み
            bd.WriteRaster(0, 0, iW, iH, dV, iW, iH, 0, 0);
            bd.FlushCache();
        }
        dsOut.SetProjection("GEOGCS[\"JGD2000\",DATUM[\"Japanese_Geodetic_Datum_2000\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6612\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4612\"]]");
        dsOut.FlushCache();
    }
}
/// <summary>
/// 一様乱数を取得する
/// </summary>
/// <returns>乱数:-1~+1</returns>
public static double GetRandom()
{
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] bs = new byte[sizeof(Int32)];
    rng.GetBytes(bs);
    int iR = System.BitConverter.ToInt32(bs, 0);
    return ((double)iR / Int32.MaxValue);
}

public static void InitGdal()
{
    const string sGdalDir = @"C:\Program Files\GDAL";
    string sVal;

    //PATH
    sVal = Environment.GetEnvironmentVariable("PATH") + ";" +
    sGdalDir + ";" +
    Path.Combine(sGdalDir, "csharp") + ";" +
    Path.Combine(sGdalDir, "gdal-data") + ";" +
    Path.Combine(sGdalDir, "gdalplugins") + ";" +
    Path.Combine(sGdalDir, "projlib");
    Environment.SetEnvironmentVariable("PATH", sVal);

    //GDAL_DATA
    Environment.SetEnvironmentVariable("GDAL_DATA", Path.Combine(sGdalDir, "gdal-data"));
    GDAL.Gdal.SetConfigOption("GDAL_DATA", Path.Combine(sGdalDir, "gdal-data"));

    //GDAL_DRIVER(Plugins)
    Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", Path.Combine(sGdalDir, "gdalplugins"));
    GDAL.Gdal.SetConfigOption("GDAL_DRIVER_PATH", Path.Combine(sGdalDir, "gdalplugins"));

    //PROJ_LIB
    Environment.SetEnvironmentVariable("PROJ_LIB", Path.Combine(sGdalDir, "projlib"));
    GDAL.Gdal.SetConfigOption("PROJ_LIB", Path.Combine(sGdalDir, "projlib"));

    GDAL.Gdal.SetConfigOption("GDAL_CACHEMAX", "100000");
    GDAL.Gdal.SetConfigOption("CPL_TMPDIR", @".\");

    GDAL.Gdal.AllRegister();
}