Ferry Kurniawan

Every Accomplishment Start With The Decision to Try
See also: Other Geeks@INDC

SQL Query to Finding Nearest Neighbours (Spatial Data)

SQL Server 2008 menyediakan beberapa fungsi yang mendukung tipe data Basis data Spasial (geometry / geography). Untuk menghitung jarak antara dua instances anda dapat menggunakan fungsi STDistance() . Contoh penerapannya seperti berikut :

Query Berikut ini mencari 10 titik terdekat dengan titik  POINT (210000 890000) di tabel Customer

   1: DECLARE @Point geometry
   2: SET @Point = geometry::STPointFromText('POINT (210000 890000)', 26986)
   3: SELECT TOP 10
   4:   Nama
   5:   Alamat,  
   6:   Lokasi.STDistance(@Point) AS Jarak
   7: FROM
   8:   Customer
   9: ORDER BY
  10:   Lokasi.STDistance(@Point)  ASC

Query diatas benar dan dapat dijalankan namun  ternyata kurang efisien karna akan menscan semua row kemudian baru diurutkan (memerlukan waktu). Solusi yang dapat digunakan untuk memberikan efisiensi maka anda dapat menggunakan tambahan fungsi STBuffer() dan Filter() seperti berikut :

   1: DECLARE @Point geometry
   2: SET @Point = geometry::STPointFromText('POINT (210000 890000)', 26986)
   3:  
   4: DECLARE @Cari geometry
   5: SET @Cari = @Point.STBuffer(500)
   6:  
   7: SELECT TOP 10
   8:   Nama
   9:   Alamat,  
  10:   Lokasi.STDistance(@Point) AS Jarak
  11: FROM
  12:   Customer
  13: WHERE
  14:   Lokasi.Filter(@Cari) = 1

Query tersebut akan mencari 10 titik terdekat namun sudah difilter terlebih dahulu yang berada dalam radius 500 meter.

Implementasi di Web Application (menggunakan control ASPMap)

1. Download dan Attach Database GIS yang dapat diunduh disini.

2. Buatlah Stored Procedure seperti berikut ini

   1: Create procedure [dbo].getPoint(@x float , @y float,@tipe varchar(30))  
   2: as
   3: Begin
   4: DECLARE @titik geometry
   5: SET @titik =  geometry::Point(@x,@y,0)
   6: DECLARE @cari geometry
   7: SET @cari = @titik.STBuffer(0.005)
   8:  
   9: SELECT [name]
  10:       ,[type]
  11:       ,[geom].STAsText(),
  12:       geom.STDistance(@titik) AS Distance
  13: FROM
  14:   points 
  15: WHERE
  16: geom.Filter(@cari) = 1
  17: and [type]=@tipe
  18: End

3. Buka Visual Studio anda buat website baru, beri nama dengan GazaMap kemudian tambahkan ASPMap control ke halaman default.aspx seperti berikut :

1

4. Tambahkan Code seperti berikut.

   1: Imports System
   2: Imports System.Data
   3: Imports System.Data.SqlClient
   4: Imports AspMap
   5: Imports AspMap.Web
   6: Partial Class _Default
   7:     Inherits System.Web.UI.Page
   8:     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   9:         LayerFromSHP()
  10:         If IsPostBack = False Then
  11:             LoadBangunan()
  12:         End If
  13:     End Sub
  14:     Private Sub LayerFromSHP()
  15:         Dim layer As AspMap.Layer
  16:         Map1.MapUnit = MeasureUnit.Meter
  17:         Dim MapDir As String = MapPath("MAP/")
  18:         layer = Map1.AddLayer(MapDir & "roads.shp")
  19:         layer.LabelField = "name"
  20:         layer.ShowLabels = True
  21:         layer.LabelFont.Color = Drawing.Color.Indigo
  22:         layer.LabelFont.Name = "Verdana"
  23:         layer.LabelFont.Size = 12
  24:         layer.LabelFont.Bold = True
  25:         layer.LabelStyle = LabelStyle.Default
  26:     End Sub
  27:     Private Sub LoadLayerFromDB(ByVal x As Double, ByVal y As Double, ByVal strTipe As String)
  28:         Dim cn As New SqlConnection("Data Source=PDI-APP-LAPTOP\MOBILE;Initial Catalog=GIS;Trusted_Connection=yes;")
  29:         cn.Open()
  30:         Dim cmd As New SqlCommand("getPoint " & x & "," & y & ",'" & strTipe & "'", cn)
  31:         Dim rdr As SqlDataReader
  32:  
  33:         Map1.Markers.Clear()
  34:         rdr = cmd.ExecuteReader()
  35:         While rdr.Read
  36:             Dim strTemp() As String
  37:             Dim strPoint As String
  38:             Dim intPosisi As Byte
  39:             intPosisi = InStr(Trim("" & rdr(2)), "(", CompareMethod.Text)
  40:             strPoint = Right(Trim("" & rdr(2)), Len(Trim("" & rdr(2))) - intPosisi)
  41:             strPoint = Left(strPoint, Len(strPoint) - 1)
  42:             strTemp = Split(strPoint, " ")
  43:  
  44:             Dim marker As Marker = New Marker(New AspMap.Point(Val(strTemp(0)), Val(strTemp(1))), Trim("" & rdr(0)), "Nama Bangunan : " & Trim("" & rdr(0)) & "<BR>" & "Jarak dari titik : " & Val("" & rdr(3)).ToString)
  45:             Map1.Markers.Add(marker)
  46:  
  47:         End While
  48:         rdr.Close()
  49:         cmd = Nothing
  50:         cn.Close()
  51:         cn = Nothing
  52:     End Sub
  53:     Sub LoadBangunan()
  54:         Dim cn As New SqlConnection("Data Source=PDI-APP-LAPTOP\MOBILE;Initial Catalog=GIS;Trusted_Connection=yes;")
  55:         cn.Open()
  56:         Dim cmd As New SqlCommand("SELECT DISTINCT [type]   FROM  [points]", cn)
  57:         Dim rdr As SqlDataReader
  58:  
  59:         ddlTipe.Items.Clear()
  60:         rdr = cmd.ExecuteReader()
  61:         While rdr.Read
  62:             ddlTipe.Items.Add(Trim("" & rdr(0)))
  63:         End While
  64:         rdr.Close()
  65:         cmd = Nothing
  66:         cn.Close()
  67:         cn = Nothing
  68:     End Sub
  69:     Protected Sub Map1_InfoTool(ByVal sender As Object, ByVal e As AspMap.Web.InfoToolEventArgs) Handles Map1.InfoTool
  70:         Dim Titik As New AspMap.Point
  71:         Titik = e.InfoPoint
  72:         LoadLayerFromDB(Titik.X, Titik.Y, ddlTipe.SelectedValue)
  73:     End Sub
  74: End Class

5. Jalankan kemudian pilih tipe bangunannya, klik icon InfoTool klik peta  di sembarang Peta “Gaza” maka akan tampil bangunan terdekat seperti berikut.

 

2

3

 

6. Source Code dapat didownload disini

7. Selamat mencoba, Semoga Bermanfaat dan Terima Kasih.

8. Tak lupa saya berdoa semoga bumi Palestina selalu dalam lindungan ALLAH S.W.T  dan Semoga tercipta Perdamaian di Timur Tengah. Amin.

Share this post: | | | |

Comments

No Comments