我從SQL空間數據庫(C#中的DbGeometry)中檢索一個複雜多邊形。複雜意味着這個多邊形被定義爲一個外部環和一個或多個內部環(如甜甜圈)。如何在一組簡單多邊形中分割多邊形
是否有一種簡單的方法可以將這個複雜的多邊形轉換爲一組簡單的多邊形。一個簡單的多邊形是一個沒有內環的多邊形。
感謝, 的Mickaël
我從SQL空間數據庫(C#中的DbGeometry)中檢索一個複雜多邊形。複雜意味着這個多邊形被定義爲一個外部環和一個或多個內部環(如甜甜圈)。如何在一組簡單多邊形中分割多邊形
是否有一種簡單的方法可以將這個複雜的多邊形轉換爲一組簡單的多邊形。一個簡單的多邊形是一個沒有內環的多邊形。
感謝, 的Mickaël
我一直在玩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
)
根據我的理解,你想簡化一個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);
從本質上講,它重新創建幾何原樣但沒有任何漏洞。我真的很喜歡把這些放在一起的挑戰! :-)
感謝您的幫助,但這不是我所期待的。對於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
@ mvera所以你說的是你想保留這個洞,但不是一個洞。換句話說,您想要根據需要以多種方式切割幾何圖形,以便能夠在孔周圍切割,但是多邊形的外觀就好像它仍然有孔一樣?如果是這樣,有什麼用?你想達到什麼目的?這當然不是簡化它。 –
您是在尋找外邊界還是代表由外邊界(無孔)定義的多邊形的區域? –
不,我搜索一組覆蓋與具有孔的多邊形相同區域的多邊形。對於甜甜圈我想檢索一個「C」和一個倒「C」。 – mvera
我不明白「C」和倒「C」的評論。也許一些明確的(但簡單的)日子會有所幫助。 –