2012-05-08 55 views
6

我有一個數據庫表,當前在SRID 27700(英國國家網格)中包含幾何數據。雖然檢索數據,但我需要將其轉換爲SRID 4326(WGS84)。有什麼方法可以將PostGIS中發現的函數(如ST_Transform)應用於我的數據以獲得我需要的結果?將一個幾何圖形從一個SRID轉換到另一個SRID

注:該解決方案需要能夠使用T-SQL,而不是存儲過程等。我必須能夠建立一個聲明,並將它後來保存在一個表作爲一個字符串字段檢索來實現。這是因爲我的解決方案是數據庫不可知的。

我目前做這在甲骨文的方式如下:

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

回答

7

你可以包裝類似的DotNetCoords SQL CLR函數來做到這一點。

在這裏看到: - http://www.doogal.co.uk/dotnetcoords.php

我包裹在一個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 

然後您就需要創建一個SQL Server功能接口到CLR函數: -

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) 

要在ResultSet使用它,你需要使用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 
10.3453417606796 -3.19252323679263 

(10 row(s) affected) 
+1

儘管目前我的情況未經測試,但它似乎是迄今爲止我遇到的我的問題的最佳解決方案,而且我看不出實施它時存在問題。感謝您花時間發佈它。我已經把賞金賞給了你。 – CSharpened

+2

謝謝,我沒有時間進一步研究它,但將庫的所有功能作爲CLR函數實施並對其進行排序,以便安裝「SAFE」版權即可。 –

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 - 但它不會幫助你,因爲他們不支持你正在談論的投影。

因此,您需要採用不同的解決方案 - 預處理數據以添加具有預計值的新列,或者在您的代碼中重新投影。

相關問題