7

現在、SRID 27700 (British National Grid) のジオメトリ データを保持しているデータベース テーブルがあります。ただし、データを取得する際に、SRID 4326 (WGS84) に変換する必要があります。必要な結果を得るために、PostGIS にある ST_Transform などの関数をデータに適用する方法はありますか?

注: ソリューションは、ストアド プロシージャなどではなく、T-SQL を使用して実装できる必要があります。ステートメントを作成し、後で取得するために文字列フィールドとしてテーブルに保存できる必要があります。これは、私のソリューションがデータベースに依存しないためです。

私が現在Oracleでこれを行っている方法は次のとおりです。

select CLUSTER_ID, 
       NUM_POINTS, 
       FEATURE_PK, 
       A.CELL_CENTROID.SDO_POINT.X, 
       A.CELL_CENTROID.SDO_POINT.Y, 
       A.CLUSTER_CENTROID.SDO_POINT.X, 
       A.CLUSTER_CENTROID.SDO_POINT.Y, 
       TO_CHAR (A.CLUSTER_EXTENT.GET_WKT ()),  
       TO_CHAR (A.CELL_GEOM.GET_WKT ()), 
       A.CLUSTER_EXTENT.SDO_SRID 
from (SELECT CLUSTER_ID, 
             NUM_POINTS, 
             FEATURE_PK, 
             SDO_CS.transform (CLUSTER_CENTROID, 4326) cluster_centroid,
             CLUSTER_EXTENT, 
             SDO_CS.transform (CELL_CENTROID, 4326) cell_centroid, 
             CELL_GEOM FROM :0) a  
where sdo_filter( A.CELL_GEOM, 
                  SDO_CS.transform(mdsys.sdo_geometry(2003, :1, NULL, mdsys.sdo_elem_info_array(1,1003,3),mdsys.sdo_ordinate_array(:2, :3, :4, :5)),81989)) = 'TRUE'

PostGISを使用するPostgreSQLでは、次のようにしています:

select CLUSTER_ID, 
       NUM_POINTS, 
       FEATURE_PK, ST_X(a.CELL_CENTROID), 
       ST_Y(a.CELL_CENTROID), 
       ST_X(ST_TRANSFORM(a.CLUSTER_CENTROID, 4326)),  
       ST_Y(ST_TRANSFORM(a.CLUSTER_CENTROID, 4326)), 
       ST_AsText(a.CLUSTER_EXTENT),  
       ST_AsText(a.CELL_GEOM), 
       ST_SRID(a.CLUSTER_EXTENT)  
FROM (SELECT CLUSTER_ID, 
      NUM_POINTS, 
      FEATURE_PK, 
      ST_TRANSFORM(ST_SetSRID(CLUSTER_CENTROID, 27700), 4326) cluster_centroid, 
      CLUSTER_EXTENT, 
      ST_TRANSFORM(ST_SetSRID(CELL_CENTROID, 27700), 4326) cell_centroid, 
      CELL_GEOM 
from :0) AS a 
where ST_Intersects(ST_Transform(ST_SetSRID(a.CELL_GEOM, 27700), :1), ST_Transform(ST_GeomFromText('POLYGON(('||:2||' '||:3||', '||:4||' '||:3||', '||:4||' '||:5||', '||:2||' '||:5||', '||:2||' '||:3||'))', 4326), :1))
4

2 に答える 2

10

これを行うには、SQL CLR 関数で DotNetCoords のようなものをラップできます。

ここを参照してください: - http://www.doogal.co.uk/dotnetcoords.php

座標を Easting/Northing から Lat/Long に変換する CLR 関数にラップしました。これはあなたが求めているものだと思います。CLR 関数が実装されると、純粋な SQL ソリューションになります (つまり、すべてをストアド プロシージャまたはビューで実行できます)。

編集:明日仕事に着いたら、ここにサンプルコードをいくつか投稿します。

編集: http://www.doogal.co.uk/dotnetcoords.phpからソース コードをダウンロードする必要があります。それを開いて変更するには、Visual Studio が必要です。ライブラリのドキュメントはこちらhttp://www.doogal.co.uk/Help/Index.html

次にできることは、次のようなソース ファイルに新しいクラスを追加できることです。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using DotNetCoords;
using Microsoft.SqlServer.Server;

/// <summary>
/// Sql Server CLR functions for the DotNetCoords library.
/// </summary>
public class CLRFunctions
{

    /// <summary>
    /// Coordinateses the enumerable.
    /// </summary>
    /// <param name="Easting">The easting.</param>
    /// <param name="Northing">The northing.</param>
    /// <returns></returns>
    private static IEnumerable<OSRef> CoordinatesEnumerable(double Easting, double Northing)
    {
        return new List<OSRef> { new OSRef(Easting,Northing) };
    }

    /// <summary>
    /// Toes the lat long.
    /// </summary>
    /// <param name="Easting">The easting.</param>
    /// <param name="Northing">The northing.</param>
    /// <returns></returns>
    [SqlFunction(FillRowMethodName = "FillRow")]
    public static IEnumerable ToLatLong(double Easting, double Northing)
    {
        return CoordinatesEnumerable(Easting, Northing);
    }

    /// <summary>
    /// Fills the row.
    /// </summary>
    /// <param name="obj">The obj.</param>
    /// <param name="Lat">The lat.</param>
    /// <param name="Long">The long.</param>
    private static void FillRow(Object obj, out SqlDouble Lat, out SqlDouble Long)
    {
        OSRef Coordinates = (OSRef)obj;
        LatLng latlong = Coordinates.ToLatLng();
        latlong.ToWGS84();
        Lat = new SqlDouble(latlong.Latitude);
        Long = new SqlDouble(latlong.Longitude);
    }

}

次に、アセンブリをビルドしてSQL Serverにインポートする必要があります(パスを独自の場所に置き換えます)(何らかの理由で、PERMISSION_SETが「SAFE」の場合、アセンブリをインストールできないため、本番環境にインストールする前にこれを最初にソートします)。

CREATE ASSEMBLY DotNetCoords
FROM N'C:\Projects\DotNetCoords\bin\Debug\DotNetCoords.dll'
WITH PERMISSION_SET = UNSAFE
GO

次に、CLR 関数に接続する SQL Server 関数を作成する必要があります。

CREATE FUNCTION dbo.ToLatLong(@Easting float, @Northing float)
RETURNS TABLE
(Latitude float null, Longitude float null) with execute as caller
AS
EXTERNAL NAME [DotNetCoords].[CLRFunctions].[ToLatLong]

これがそのときインストールされた CLR 関数です。

次に、関数を SQL Server から直接呼び出して変換を行うことができるはずです (この投稿では数字を混同しているため、匿名性を維持しているため、ここでは意味をなさない可能性がありますが、関数は正常に動作します)。

/*------------------------
SELECT Latitude, Longitude FROM dbo.ToLatLong(327262, 357394)
------------------------*/
Latitude            Longitude
52.13413530182533       -9.34267170569508

(1 row(s) affected)

結果セットで使用するには、CROSS APPLY 句を使用する必要があります。

/*------------------------
SELECT TOP 2    a.[Column 0] AS osaddessp,
                            a.[Column 9] AS east,
                            a.[Column 10] AS north,
                            c.[Latitude] AS lat,
                            c.[Longitude] AS long
FROM    MyTable AS a CROSS APPLY ToLatLong (a.[Column 9], a.[Column 10]) AS c;
------------------------*/
osaddessp       east    north   lat         long
100134385607    327862  334794  52.3434530182533    -2.19342342569508
100123433149    780268  353406  52.3453417606796    -3.19252323679263

(10 row(s) affected)
于 2012-05-29T13:20:51.197 に答える
2

残念ながら、これは単に不可能です。SQL Server Spatial Tools にはいくつかの再投影関数が用意されていますが、それらは非常に少数の投影にのみ使用できます (必要な投影ではありません)。

SQL サーバー ツールの例があります-- https://bitbucket.org/geographika/sql-server-spatial-tools/src/5ca44b55d3f3/SQL%20Scripts/projection_example.sql -- しかし、それは役に立ちません。あなたが話している投影をサポートしていません。

そのため、別のソリューションを採用する必要があります。データを前処理して、投影された値を持つ新しい列を追加するか、コードで再投影します。

于 2012-05-29T14:30:50.447 に答える