2 Stimmen

GIS findet Punkte (lange Latten), die in einem Polygon enthalten sind, das als eine Sammlung von langen Latten ausgedrückt wird

Ich versuche, alle Datenelemente zu finden, die Long/Lats haben, die von einem Polygon enthalten sind, das aus einem Array von Long Lats besteht, das viele Punkte sein könnten. Ich weiß, Sie können diese Art von Sachen mit den neuen geospacial Datentypen in SQL 2008 tun, aber ich bin mit SQL 2005 und C#. Wäre dies am besten auf am DB-Ende oder in C# getan werden.

Danke.

1voto

Mikko Rantanen Punkte 7707

Das klingt nach etwas, das Kopfschmerzen bereitet, wenn es in T-SQL ausgeführt wird (was mehr oder weniger alles ist). Natürlich hängt es von der Komplexität der Polygone und der Art und Weise die Datenelemente befinden, aber in der Regel die einfachste und ein mäßig effizienter Ansatz könnte sein, einige anfängliche Berechnungen in C# zu tun, die die Datenelemente in einer sehr groben Weise begrenzt. Also etwas wie das Folgende.

  1. Berechnen Sie die groben Grenzen des Polygons in C#.
  2. Holen Sie alles, was innerhalb dieser Grenzen liegt, vom SQL-Server.
  3. Führen Sie die endgültige genaue Filterung in C# durch.

Die Leistung hängt natürlich davon ab, wie gut Sie die ursprünglichen Grenzen berechnen können. Ich würde zunächst nur mit einem einfachen Begrenzungsrechteck beginnen und sehen, ob die Leistung ausreicht.

1voto

George Mastros Punkte 23326

Ich habe einen Code für SQL2000 geschrieben, um dies zu tun. Er verwendet die "Winkel"-Methode zur Bestimmung, ob ein Punkt innerhalb eines Polygons liegt.

Erstens, die benutzerdefinierte Funktion GetAngle:

ALTER Function [dbo].[GetAngle](
@Ax Decimal(8,5), 
@Ay Decimal(8,5), 
@Bx Decimal(8,5), 
@By Decimal(8,5), 
@Cx Decimal(8,5), 
@Cy Decimal(8,5))

Rückgabe Float Als Begin

Declare @dot_product Float
Declare @cross_product Float

Declare @BAx Decimal(8,5)
Declare @BAy Decimal(8,5)
Declare @BCx Decimal(8,5)
Declare @BCy Decimal(8,5)

--' Get the vectors' coordinates.
Set @BAx = Sign(@Ax - @Bx) * dbo.CalculateDistance(@Ax, @Ay, @Bx, @Ay)
Set @BAy = Sign(@Ay - @By) * dbo.CalculateDistance(@Ax, @Ay, @Ax, @By)
Set @BCx = Sign(@Cx - @Bx) * dbo.CalculateDistance(@Cx, @Cy, @Bx, @Cy)
Set @BCy = Sign(@Cy - @By) * dbo.CalculateDistance(@Cx, @Cy, @Cx, @By)

--' Calculate the dot product.
Set @dot_product = @BAx * @BCx + @BAy * @BCy

--' Calculate the Z coordinate of the cross product.
Set @cross_product = @BAx * @BCy - @BAy * @BCx

--' Calculate the angle.
return ATn2(@cross_product, @dot_product)

Ende


Als Nächstes nehme ich an, dass es eine Tabellenvariable mit Breiten-/Längenpaaren und einer Sequenznummer gibt (die die Reihenfolge angibt, in der die LAT/LONG-Paare das Polygon definieren). Es ist wichtig, dass der erste Punkt in dieser Tabelle mit dem letzten Punkt in der Tabelle identisch ist.

Außerdem habe ich mehrere Variablen für den minimalen und maximalen Breitengrad und Längengrad. Auf diese Weise wird ein Begrenzungsrahmen erstellt, so dass ich Punkte, die NICHT innerhalb eines rechteckigen Bereichs liegen, der das Polygon begrenzt, schnell ausschließen kann.

Select  Address.AddressId
From    @Temp As A
        Inner Join @Temp As B
            On A.SequenceNumber = B.SequenceNumber - 1
        Inner Join Address
            On Address.XCoord Between @MinLongitude And @MaxLongitude
            And Address.YCoord Between @MinLatitude And @MaxLatitude
Group By Address.AddressId
Having Abs(Sum(dbo.GetAngle(A.Longitude, A.Latitude, Address.XCoord, Address.YCoord, B.Longitude, B.Latitude))) > 3.14

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X