2012-05-08 21 views
6

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

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

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' 

が、私はこのようにそれをやっている:

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)) 

答えて

7

あなたは中DotNetCoordsのようなものを包むことができ、次のように

私は現在Oracleでこれをやっている方法ですこれを行うにはSQL CLR関数を使用します。

はこちらを参照してください: - 私はあなたが求めているものだと思う/ロングをLATし東距/北距からの座標を変換するために、CLR機能に包みましたhttp://www.doogal.co.uk/dotnetcoords.php

。 CLR機能が実装されたら、それは純粋なSQLソリューションです(つまり、ストアドプロシージャまたはビューですべてを実行できます)。

編集:私は明日に仕事に出たときにサンプルコードをここに掲載します。うまくいけば助けになるでしょう。

EDIThttp://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句を適用使用する必要があります -

/*------------------------ 
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 
10.3453417606796 -3.19252323679263 

(10 row(s) affected) 
+1

これは私の状況では現在テストされていませんが、これまでのところ私の問題の最も良い解決策であると思われますが、実装に問題があるとは思えません。投稿していただきありがとうございます。私はあなたに恩恵を授与しました。 – CSharpened

+2

ありがとう、私はそれ以上見て時間があったが、CLRの機能としてライブラリのすべての機能を実装し、それを並べ替えるように 'SAFE'のpesmissionsでインストールするのが良いでしょう。 –

2

残念ながら、これは単純に不可能です。SQL Server Spatial Toolsにはいくつかの再投影機能が用意されていますが、必要なものだけでなく、非常に少数の投影にすぎません。

example from SQL server tools - https://bitbucket.org/geographika/sql-server-spatial-tools/src/5ca44b55d3f3/SQL%20Scripts/projection_example.sqlがありますが、あなたが話しているプロジェクションをサポートしていないため、お手伝いできません。

したがって、データを前処理して投影値を含む新しい列を追加するか、コードに再投影するなど、別のソリューションを採用する必要があります。

関連する問題