2015-09-14 156 views
0

我從SQL空間數據庫(C#中的DbGeometry)中檢索一個複雜多邊形。複雜意味着這個多邊形被定義爲一個外部環和一個或多個內部環(如甜甜圈)。如何在一組簡單多邊形中分割多邊形

是否有一種簡單的方法可以將這個複雜的多邊形轉換爲一組簡單的多邊形。一個簡單的多邊形是一個沒有內環的多邊形。

感謝, 的Mickaël

+0

您是在尋找外邊界還是代表由外邊界(無孔)定義的多邊形的區域? –

+0

不,我搜索一組覆蓋與具有孔的多邊形相同區域的多邊形。對於甜甜圈我想檢索一個「C」和一個倒「C」。 – mvera

+0

我不明白「C」和倒「C」的評論。也許一些明確的(但簡單的)日子會有所幫助。 –

回答

0

我一直在玩DbGeometries了一會兒,this article提供了一個很好的工具來操作它。

我懷疑這會不會像return myGeo.ExteriorRing;這麼簡單,在意見要求,來到這裏的一些代碼,我來到(基於文章):

//handling of LineStrings (I use this to build WPF Path for example) 
     private static object LineStringToSomething(DbGeometry sqlGeometry) 
     { 
      object result = null; 
      DbGeometry curPoint; 
      System.Windows.Point startPoint = new System.Windows.Point() 
      { 
       X = sqlGeometry.PointAt(1).XCoordinate.Value, 
       Y = sqlGeometry.PointAt(1).YCoordinate.Value 
      }; 

      curPoint = sqlGeometry.PointAt(1); 

      for (int i = 2; i <= sqlGeometry.PointCount; i++) 
      { 
       //Do something with the line between curPoint and PointAt(i) 

       curPoint = sqlGeometry.PointAt(i); 
      } 

      return result; 
     } 

     //Defines an extension method on DbGeometry objects 
     //usage : 
     // myOwnGeometry = myGeo.AsSimpleGeometry(); 
     public static object AsSimpleGeometry(this DbGeometry sqlGeometry) 
     { 
      object result = null; 

      switch (sqlGeometry.SpatialTypeName.ToLower()) 
      { 
       case "point": 
        //Here we found a point 

        return result; 

       case "polygon": 
        // A Spacial Polygon is a collection of Rings 
        // A Ring is a Closed LineString, i.e. a collection of lines. 
        List<object> lotOfGeos = new List<object>(); 
        // Outer Ring 
        return LineStringToSomething(sqlGeometry.ExteriorRing); 

        // Inner Rings (holes in the donut) 
        for (int i = 1; i <= sqlGeometry.InteriorRingCount; i++) 
        { 
         //just comment to ignore the inner loops 
         lotOfGeos.Add(LineStringToSomething(sqlGeometry.InteriorRingAt(i))); 
        } 

        return lotOfGeos; 

       case "linestring": 
        // Return a PathFigure 
        return LineStringToSomething(sqlGeometry); 

       case "multipoint": 
       case "multilinestring": 
       case "multipolygon": 
       case "geometrycollection": 
        //Here we handle a collection of points, polygons and/or lines 
        List<object> moreGeos = new List<object>(); 
        for (int i = 1; i <= sqlGeometry.ElementCount.Value; i++) 
        { 
         //Simply calling the same method on each item 
         moreGeos.Add(sqlGeometry.ElementAt(i).AsSimpleGeometry()); 
        } 

        return moreGeos; 

       default: 
        // Unrecognized Type 
        // Shall not happen 
        return null; 
      } 
     } 

由於我不知道到底是什麼你我試圖用你的幾何來實現,我不能更具體地處理地理數據(特別是在LineStringToSomething

+1

因爲它沒有真正回答這個問題,所以這會更好。 – juharr

+0

對不起,但我沒有想過重新發布別人的代碼。只有很多線條可以評論/剪切以獲得「簡單」多邊形。 – xum59

+0

感謝您的回答。但是我沒有看到文章中一組簡單多邊形中複雜多邊形的轉換位置。我不覺得幾何課會給我我要找的東西。 – mvera

0

根據我的理解,你想簡化一個POLYGON或MULTIPOLYGON幾何實例以實質上刪除所有的洞。不清楚的是當實例是MULTIPOLYGON時你期望的結果,但是我假設你想要在同一個實例中的所有外部邊界。

因此,我建議如下:

首先,定義一個方法來簡化幾何圖形:

using Microsoft.SqlServer.Types; 
    using System.Data.Entity.Spatial; 

    private static DbGeometry GetSimpleDbGeography(DbGeometry input) 
    { 
     // We can create geometry using Microsoft.SqlServer.Types.SqlGeometryBuilder 
     // We have to use this to reconstruct the geometry we want from the input as DbGeometry.ExteriorRing() returns a LINESTRING which is no good to us 
     SqlGeometryBuilder builder = new SqlGeometryBuilder(); 

     // We MUST set an SRID 
     builder.SetSrid(0); 

     OpenGisGeometryType ourType; 

     // We must set the type 
     if (input.SpatialTypeName.ToUpper() == "POLYGON") 
      ourType = OpenGisGeometryType.Polygon; 
     else if (input.SpatialTypeName.ToUpper() == "MULTIPOLYGON") 
      ourType = OpenGisGeometryType.MultiPolygon; 
     else 
      throw new ArgumentException("Non Polygon received."); 

     // Tell the Builder what we're creating 
     builder.BeginGeometry(ourType); 

     // This assumes we have a valid DbGeometry instance, otherwise .Value will cause an error 
     int numberOfElements = input.ElementCount.Value; 

     // Loop through each element, this will either be one (POLYGON) or more (MULTIPOLYGON) 
     for (int i = 1; i < (numberOfElements + 1); i++) 
     { 
      // BeginGeometry only required for MULTIPOLYGON 
      if (ourType == OpenGisGeometryType.MultiPolygon) 
      { 
       // Begin a POLYGON geometry 
       builder.BeginGeometry(OpenGisGeometryType.Polygon); 
      } 

      // ElementAt() is not zero-based index 
      DbGeometry element = input.ElementAt(i).ExteriorRing; 

      // Start the figure with the first point 
      builder.BeginFigure(element.StartPoint.XCoordinate.Value, element.StartPoint.YCoordinate.Value); 

      // Lopp through remaining points 
      for (int j = 2; j < (element.PointCount.Value + 1); j++) 
      { 
       // PointAt() is not zero-based index 
       builder.AddLine(element.PointAt(j).XCoordinate.Value, element.PointAt(j).YCoordinate.Value); 
      } 

      // End the current polygon 
      builder.EndFigure(); 

      // EndGeometry only required for MULTIPOLYGON 
      if (ourType == OpenGisGeometryType.MultiPolygon) 
      { 
       // End the current Geometry 
       builder.EndGeometry(); 
      } 
     } 

     // Finalise the geometry 
     builder.EndGeometry(); 

     // Convert the construsted geometry back to a DbGeometry instance 
     DbGeometry finalGeometry = DbGeometry.FromBinary(builder.ConstructedGeometry.STAsBinary().Buffer); 

     return finalGeometry; 
    } 

現在只需調用是這樣的:

// Two sample donuts 
DbGeometry donut1 = DbGeometry.FromText("POLYGON((0 0, 3 0, 3 3, 0 3, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))", 0); 
DbGeometry donut2 = DbGeometry.FromText("POLYGON((10 10, 13 10, 13 13, 10 13, 10 10),(11 11, 12 11, 12 12, 11 12, 11 11))", 0); 

// A merged, double-donut 
DbGeometry doubleDonut = donut1.Union(donut2); 

// Produces POLYGON((0 0, 3 0, 3 3, 0 3, 0 0)) 
DbGeometry donut1_simple = GetSimpleDbGeography(donut1); 

// Produces MULTIPOLYGON(((10 10, 13 10, 13 13, 10 13, 10 10)),((0 0, 3 0, 3 3, 0 3, 0 0))) 
DbGeometry doubleDonut_simple = GetSimpleDbGeography(doubleDonut); 

從本質上講,它重新創建幾何原樣但沒有任何漏洞。我真的很喜歡把這些放在一起的挑戰! :-)

+0

感謝您的幫助,但這不是我所期待的。對於donut1_simple我預計:MULTIPOLYGON(((1.5 0,1.5 1,1 1,1 2,1.5 2,1.5 3,0 3,0 0,1.5 0)),((1.5 0,3 0,3 3,1.5 3,1.5 2,2 2,2 1,1.5 1,1.5 0)))。這種幾何形狀由沒有孔的多邊形構成,但形狀相同,面積與圓環1相同。 – mvera

+0

@ mvera所以你說的是你想保留這個洞,但不是一個洞。換句話說,您想要根據需要以多種方式切割幾何圖形,以便能夠在孔周圍切割,但是多邊形的外觀就好像它仍然有孔一樣?如果是這樣,有什麼用?你想達到什麼目的?這當然不是簡化它。 –