2012-04-12 64 views
3

我從某處導入了〜1000個路徑到我的postgis數據庫到一個線串字段。Postgis重新排列混合線串塊/ max_segment_length(線串)?

編輯)我的表是這樣的

+---------+---------------+------------------+ 
| id(int) | name(varchar) | path(LINESTRING) | 
+---------+---------------+------------------+ 
| 123  | foo   | 000002...  | 
| 124  | bar   | 000002...  | 

我有這樣的每個路徑被分成塊的問題,而這些塊在某些情況下進行混合。

假設在點數目50和70劃分線串:

  1. 堆塊A:點1-50
  2. 組塊B:點51-70
  3. 組塊C:點71-100

當我遷移的到我的數據庫,他們搞混,所以導致線串最終可能是這樣的:

  1. 堆塊A:點1-50
  2. 組塊C:點71-100
  3. 組塊B:點51-70

所以產生50至71的跳躍,並從100另一51

編輯)當我進口的那些塊我認爲他們被要求分成的路徑,但事實是,有的被混了,這讓我的一些線串的是與自己的積分排序,如第二個例子。我想要能夠重新排列這些塊(點),所以我想構建一個SQL查詢來檢測哪些路徑有混合點,然後我可以手動(使用一個使用openlayers的工具)重新排列它們。

,希望有一個SQL更新查詢來解決這個問題,但我認爲,檢測更容易(我相信也有有錯誤的路徑〜5%或更少)

EDIT3:我認爲用於檢測的腳本可以檢查路徑是否包含一對連續的點太遠。也許一個從包含最長段的路徑排序路徑的SQL會很好。

我該如何製作一個函數來獲取線段中最大段的長度?

在這裏,我展示一個例子: 這是它是如何在數據庫中 a bad way

這是我希望它被固定 a good (fixed) way

EDIT4:就像我計劃在EDIT3,可以使用ST_NPoints()ST_PointN()來寫一個函數來查找線串中兩個連續點之間的最長距離,該線串通過線串的點迭代,然後可以查詢具有該最長距離的路徑。這種距離太長的線串很可能會導致所描述的問題。這樣我就能夠檢測到它們,並手動修復它們。

從檢測SQL的結果會是這樣的:

           |ordered by this| 
+---------+---------------+------------------+---------------+ 
| id(int) | name(varchar) | path(LINESTRING) | msbtcp(int) | 
+---------+---------------+------------------+---------------+ 
| 123  | foo   | 000002...  | 1000   | 
| 124  | bar   | 000002...  | 800   | 

* msbtcp將是函數的結果:max_separation_between_two_consecutive_points(path)

回答

3

這聽起來有點繞口,但是如果你只是在一個線串連續兩個點之間的最大距離後是:

CREATE OR REPLACE FUNCTION max_distance_in_linestring(line geometry) RETURNS float as $BODY$ 
DECLARE 
    i integer; 
    n integer; 
    d float; 
    m float; 
BEGIN 
    d := 0; 
    n := ST_NPoints(line); 
    i := 2; 
    LOOP 
     EXIT WHEN i >= n; 
     m := ST_Distance(ST_PointN(line,i-1),ST_PointN(line,i)); 
     -- use for lon,lats: 
     -- m := ST_Distance(ST_PointN(line,i-1)::geography,ST_PointN(line,i)::geography); 
     IF m > d THEN 
      d := m; 
     END IF; 
     i := i + 1; 
    END LOOP; 
    RETURN d; 
END; 
$BODY$ 
LANGUAGE plpgsql; 

SELECT max_distance_in_linestring('LINESTRING(0 0, 1 1, 2 2)'::geometry); 
SELECT max_distance_in_linestring('LINESTRING(0 0, 4 3, 2 2)'::geometry); 

你可能要重新投放ST_PointN調用::對於地理以米爲單位獲得距離。

的SQL會是這樣的:

SELECT 
    name, path 
FROM 
    paths 
ORDER BY 
    max_distance_in_linestring(path) DESC 
+0

'線幾何(LINESTRING)'拋出一個錯誤,所以我將它改爲'線幾何'。像檢測的魅力一樣工作。 – jperelli 2012-04-29 14:30:13

+1

啊,我在用PostGIS-2.0;你必須在1.5? – 2012-04-30 02:30:52

+0

這就對了我正在使用PostGIS 1.5 – jperelli 2012-05-01 16:16:28

0

那麼你想知道什麼是片段的鏈接方式,所以你需要每一段的第一個和最後一個點與所有其他段比較:

SELECT foo.gid as segment_a, bar.gid as segment_b 
    FROM 
     segments AS foo, 
     (SELECT the_geom, gid FROM segments) AS bar 
    WHERE 
     bar.gid != foo.gid AND (-- avoid same segments 
     ST_DWithin( 
       ST_GeometryN(foo.the_geom, ST_NumGeometries(foo.the_geom)) , -- last from foo 
       ST_GeometryN(bar.the_geom, ST_NumGeometries(bar.the_geom)) , -- last from bar 
       0.00005) OR -- precision, depends of your SRID 
     ST_DWithin( 
       ST_GeometryN(foo.the_geom, 1) , -- first from foo (start = 1 index) 
       ST_GeometryN(bar.the_geom, ST_NumGeometries(bar.the_geom)) , -- last from bar 
       0.00005) OR -- precision, depends of your SRID 
     ST_DWithin( 
       ST_GeometryN(foo.the_geom, ST_NumGeometries(foo.the_geom)) , -- last from foo 
       ST_GeometryN(bar.the_geom, 1) , -- first from bar 
       0.00005) OR -- precision, depends of your SRID 
     ST_DWithin( 
       ST_GeometryN(foo.the_geom, 1) , -- first from foo 
       ST_GeometryN(bar.the_geom, 1) , -- first from bar 
       0.00005)) -- precision, depends of your SRID 

瞧...! 您可以將此鏈接保存在新表格中,並使用ST_Union加入鏈接的片段。

+0

我覺得代碼工作如果表中的各線串是段。 我想解釋的是每個線串(只有一個字段)與自身混合。當我說「段」時,我的意思是線串的一部分,這樣一個段將是例如[ST_pointN](http://postgis.refractions.net/documentation/manual-2.0/ST_PointN.html)(線串,1) - ST_PointN(linestring,2) – jperelli 2012-04-18 18:26:48

+0

好的,好的,所以你的表的幾何類型是POINTs? – 2012-04-18 23:57:16

+0

該類型將是LINESTRING,我將用更多信息編輯該問題,對不起:) – jperelli 2012-04-19 16:06:44