Oto coś, co napisałem jakiś czas temu, co może skierować cię we właściwym kierunku.
Podczas gdy pytałeś o VB.Net, naprawdę potrzebujesz zapytania, które wykonuje „Wielki krąg Odległość " obliczenie w celu określenia odległości między dwoma punktami określonymi przez szerokość i długość geograficzną.
Przyjmij więc następujące założenia:
- Twoje dane kodu pocztowego znajdują się w jednej tabeli.
- Wspomniana tabela ma atrybuty lat i lon, które są przybliżoną centroidą kodu pocztowego
Możesz użyć zapytania LINQ to SQL, które generuje żądany zestaw wyników, używając czegoś takiego
Const EARTH_RADIUS As Single = 3956.0883313286095
Dim radCvtFactor As Single = Math.PI / 180
Dim zipCodeRadius As Integer = <Your Radius Value>
Dim zipQry = From zc In db.ZipCodes
Where zc.Zip = "<Your Zip Code>" _
Select zc.Latitude,
zc.Longitude,
ZipLatRads = RadCvtFactor * zc.Latitude,
ZipLonRads = RadCvtFactor * zc.Longitude
Dim zipRslt = zipQry.SingleOrDefault()
If zipRslt IsNot Nothing Then
Dim zcQry = From zc In db.ZipCodes _
Where zc.Latitude >= (zipRslt.Latitude - 0.5) And zc.Latitude <= (zipRslt.Latitude + 0.5) _
And zc.Longitude >= (zipRslt.Longitude - 0.5) And (zc.Longitude <= zipRslt.Longitude + 0.5) _
And Math.Abs(EARTH_RADIUS * (2 * Math.Atan2(Math.Sqrt(Math.Pow(Math.Sin(((RadCvtFactor * zc.Latitude) - zipRslt.ZipLatRads) / 2), 2) + _
Math.Cos(zipRslt.ZipLatRads) * Math.Cos(RadCvtFactor * zc.Latitude) * _
Math.Pow(Math.Sin(((RadCvtFactor * zc.Longitude) - zipRslt.ZipLonRads) / 2), 2)), _
Math.Sqrt(1 - Math.Pow(Math.Sin(((RadCvtFactor * zc.Latitude) - zipRslt.ZipLatRads) / 2), 2) + _
Math.Cos(zipRslt.ZipLatRads) * Math.Cos(RadCvtFactor * zc.Latitude) * _
Math.Pow(Math.Sin((RadCvtFactor * zc.Longitude) / 2), 2))))) <= zipCodeRadius _
Select zc
End If
Wygląda na skomplikowaną, bo tak jest. W SO są znacznie mądrzejsi ludzie, którzy mogą wyjaśnić algorytm. Po prostu zaimplementowałem to z jakiegoś kodu SQL, który znalazłem w Internecie - nie pamiętam skąd. Wyszukiwarka Google powinna Cię tam zaprowadzić.
Pierwsze zapytanie (zipQry) zwraca szerokość i długość początkowego kodu pocztowego zarówno w stopniach, jak i radianach. Wyniki te są następnie wykorzystywane do wykonania drugiego zapytania.
Pierwsza część klauzuli WHERE w drugim zapytaniu:
Where zc.Latitude >= (zipRslt.Latitude - 0.5) And zc.Latitude <= (zipRslt.Latitude + 0.5) _
And zc.Longitude >= (zipRslt.Longitude - 0.5) And (zc.Longitude <= zipRslt.Longitude + 0.5) _
Po prostu zawęziłem listę kodów pocztowych do zbadania, dzięki czemu zapytanie działa znacznie szybciej. Dodaje dowolną kwotę do szerokości geograficznej i długiej, dzięki czemu podczas wyszukiwania promienia w Kalifornii nie sprawdzasz wszystkich kodów pocztowych w Ohio. Reszta jest częścią wspomnianego algorytmu odległości od Wielkiego Koła.
Prawdopodobnie można to było zrobić w jednym zapytaniu, aby uzyskać większą wydajność, ale wtedy potrzebowałem tego w ten sposób, powody teraz dla mnie utracone.