how can I make this code run faster

S

Scott Emick

I am using the following to compute distances between two lat/long
coordinates for a store locator - (VB .NET 2003)

it seems to take a long time to iterate through like 100-150 locations -
about 10-15 seconds...I want to make the code faster. I changed it to be
multi-threaded, and it doesn't really make it any faster. The bottleneck
seems to be with the math computations.

Any ideas like changing my data types or other ideas etc would be helpful.

Thanks,

--
Scott Emick
Web Programmer
Fox International
Remove the ham from mail address if it's not spam



Option Strict On
Imports System.Threading
Imports Infragistics.Shared
Imports Infragistics.Win
Imports Infragistics.Win.UltraWinGrid

Public Class Locator
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
[...]
#End Region

Public Q As New Queue
Public R As New Queue
Shared rwl As New ReaderWriterLock
Dim dvZip As DataView
Dim srcLat As Double
Dim srcLon As Double
Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFind.Click
dvZip = New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim deg As Double
Dim min As Double
Dim sec As Double
dvZip.RowFilter = "ZCODE='" & Microsoft.VisualBasic.Left(txtZip.Text,
5) & "'"

srcLat = CDbl(dvZip(0)("lat"))

srcLon = CDbl(dvZip(0)("lon"))
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow /
DsMM1.Mailing_Master.Count) * 100)
Application.DoEvents()
Q.Enqueue(mmrow)
R.Enqueue(currow)
Dim job3 As New ThreadStart(AddressOf ComputeDistance)
Dim thread3 As New Thread(job3)

thread3.Name = "ComputeDistance"
Do Until R.Count < 20
Loop
thread3.Start()
Next
Dim dvMM01 As New DataView(DsMM1.Mailing_Master)
UltraGrid1.DataSource = dvMM01
dvMM01.Sort = "distance"
dvMM01.RowFilter = "distance<=" & txtMiles.Text
Dim band As UltraGridBand = Me.UltraGrid1.DisplayLayout.Bands(0)
band.Columns("distance").SortIndicator = SortIndicator.Ascending
band.SortedColumns.Add("distance", False, False)
End Sub
Private Sub ComputeDistance()
Dim mmr As dsMM.Mailing_MasterRow = CType(Q.Dequeue,
dsMM.Mailing_MasterRow)
Dim lat As Double
Dim lon As Double
Dim dist As Integer
Dim dvZip2 As New DataView(DsMM1.Zip)
dvZip2.RowFilter = "ZCODE='" & Mid(mmr.MMZIP, 1, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip2(0)("lat"))
lon = CDbl(dvZip2(0)("lon"))
dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
Console.WriteLine(dist)
rwl.AcquireWriterLock(60000)
mmr.Distance = dist
rwl.ReleaseWriterLock()
Else
dist = 2147483647
End If
R.Dequeue()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Show()
txtResults.Text &= "Filling location database..." & vbCrLf
Application.DoEvents()
DsMM1.EnforceConstraints = False
daMM.Fill(DsMM1)
DsMM1.WriteXml("c:\dsmm1.xml")

daZip.Fill(DsMM1)
txtResults.Text &= "Enabling Constraints." & vbCrLf
Try
DsMM1.EnforceConstraints = True
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK)
End
End Try
txtResults.Text &= DsMM1.Mailing_Master.Count.ToString & " locations
available. " & vbCrLf
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Dim dvZip As New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim lat As Double
Dim lon As Double
Dim deg As Double
Dim min As Double
Dim sec As Double
Dim dist As Integer
Dim srcLat As Double
Dim srcLon As Double
'dvZip.RowFilter = "ZCODE='" & Microsoft.VisualBasic.Left(txtZip.Text,
5) & "'"
'zlat = CStr(dvZip(0)("zlat"))
'deg = CDec(zlat.Substring(0, 2))
'min = CDec(zlat.Substring(2, 2))
'sec = CDec(zlat.Substring(4, 2))
'srcLat = deg + (min / 60) + (sec / 3600)
'zlon = CStr(dvZip(0)("zlon"))
'deg = CDec(zlon.Substring(0, 2))
'min = CDec(zlon.Substring(2, 2))
'sec = CDec(zlon.Substring(4, 2))
'srcLon = deg + (min / 60) + (sec / 3600)
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow / DsMM1.Zip.Count) * 100)
Application.DoEvents()
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(mmrow.MMZIP, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip(0)("LAT"))
mmrow.LAT = CDec(lat)
lon = CDbl(dvZip(0)("LON"))
mmrow.LON = CDec(lon)
daMM.Update(DsMM1.Mailing_Master)
'dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
mmrow.Distance = dist
Else
dist = 2147483647
End If
Next

End Sub
End Class


'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String) As
Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))
dist = CDbl(rad2deg(dist))
distance = CInt(dist * 60 * 1.1515)
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
If Abs(CDec(rad)) <> 1 Then
acos = pi / 2 - Atan(rad / Sqrt(1 - rad * rad))
ElseIf rad = -1 Then
acos = pi
End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts decimal degrees to radians :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function deg2rad(ByVal deg As Double) As Double
deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts radians to decimal degrees :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function rad2deg(ByVal rad As Double) As Double
rad2deg = CDbl(rad * 180 / pi)
End Function

End Class
 
M

Mr Newbie

Where are the computations taking place. If you are going back to location
server for the result, it will take a relatively long time ( unless you have
one locally ). If you are making the calculations yourself then without
seeing the code its a little difficult to answer really.

--
Best Regards

The Inimitable Mr Newbie º¿º


Scott Emick said:
I am using the following to compute distances between two lat/long
coordinates for a store locator - (VB .NET 2003)

it seems to take a long time to iterate through like 100-150 locations -
about 10-15 seconds...I want to make the code faster. I changed it to be
multi-threaded, and it doesn't really make it any faster. The bottleneck
seems to be with the math computations.

Any ideas like changing my data types or other ideas etc would be helpful.

Thanks,

--
Scott Emick
Web Programmer
Fox International
Remove the ham from mail address if it's not spam



Option Strict On
Imports System.Threading
Imports Infragistics.Shared
Imports Infragistics.Win
Imports Infragistics.Win.UltraWinGrid

Public Class Locator
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
[...]
#End Region

Public Q As New Queue
Public R As New Queue
Shared rwl As New ReaderWriterLock
Dim dvZip As DataView
Dim srcLat As Double
Dim srcLon As Double
Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFind.Click
dvZip = New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim deg As Double
Dim min As Double
Dim sec As Double
dvZip.RowFilter = "ZCODE='" & Microsoft.VisualBasic.Left(txtZip.Text,
5) & "'"

srcLat = CDbl(dvZip(0)("lat"))

srcLon = CDbl(dvZip(0)("lon"))
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow /
DsMM1.Mailing_Master.Count) * 100)
Application.DoEvents()
Q.Enqueue(mmrow)
R.Enqueue(currow)
Dim job3 As New ThreadStart(AddressOf ComputeDistance)
Dim thread3 As New Thread(job3)

thread3.Name = "ComputeDistance"
Do Until R.Count < 20
Loop
thread3.Start()
Next
Dim dvMM01 As New DataView(DsMM1.Mailing_Master)
UltraGrid1.DataSource = dvMM01
dvMM01.Sort = "distance"
dvMM01.RowFilter = "distance<=" & txtMiles.Text
Dim band As UltraGridBand = Me.UltraGrid1.DisplayLayout.Bands(0)
band.Columns("distance").SortIndicator = SortIndicator.Ascending
band.SortedColumns.Add("distance", False, False)
End Sub
Private Sub ComputeDistance()
Dim mmr As dsMM.Mailing_MasterRow = CType(Q.Dequeue,
dsMM.Mailing_MasterRow)
Dim lat As Double
Dim lon As Double
Dim dist As Integer
Dim dvZip2 As New DataView(DsMM1.Zip)
dvZip2.RowFilter = "ZCODE='" & Mid(mmr.MMZIP, 1, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip2(0)("lat"))
lon = CDbl(dvZip2(0)("lon"))
dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
Console.WriteLine(dist)
rwl.AcquireWriterLock(60000)
mmr.Distance = dist
rwl.ReleaseWriterLock()
Else
dist = 2147483647
End If
R.Dequeue()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Show()
txtResults.Text &= "Filling location database..." & vbCrLf
Application.DoEvents()
DsMM1.EnforceConstraints = False
daMM.Fill(DsMM1)
DsMM1.WriteXml("c:\dsmm1.xml")

daZip.Fill(DsMM1)
txtResults.Text &= "Enabling Constraints." & vbCrLf
Try
DsMM1.EnforceConstraints = True
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK)
End
End Try
txtResults.Text &= DsMM1.Mailing_Master.Count.ToString & " locations
available. " & vbCrLf
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Dim dvZip As New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim lat As Double
Dim lon As Double
Dim deg As Double
Dim min As Double
Dim sec As Double
Dim dist As Integer
Dim srcLat As Double
Dim srcLon As Double
'dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(txtZip.Text, 5) & "'"
'zlat = CStr(dvZip(0)("zlat"))
'deg = CDec(zlat.Substring(0, 2))
'min = CDec(zlat.Substring(2, 2))
'sec = CDec(zlat.Substring(4, 2))
'srcLat = deg + (min / 60) + (sec / 3600)
'zlon = CStr(dvZip(0)("zlon"))
'deg = CDec(zlon.Substring(0, 2))
'min = CDec(zlon.Substring(2, 2))
'sec = CDec(zlon.Substring(4, 2))
'srcLon = deg + (min / 60) + (sec / 3600)
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow / DsMM1.Zip.Count) * 100)
Application.DoEvents()
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(mmrow.MMZIP, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip(0)("LAT"))
mmrow.LAT = CDec(lat)
lon = CDbl(dvZip(0)("LON"))
mmrow.LON = CDec(lon)
daMM.Update(DsMM1.Mailing_Master)
'dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon,
"N")
mmrow.Distance = dist
Else
dist = 2147483647
End If
Next

End Sub
End Class


'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String)
As Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))
dist = CDbl(rad2deg(dist))
distance = CInt(dist * 60 * 1.1515)
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
If Abs(CDec(rad)) <> 1 Then
acos = pi / 2 - Atan(rad / Sqrt(1 - rad * rad))
ElseIf rad = -1 Then
acos = pi
End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts decimal degrees to radians :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function deg2rad(ByVal deg As Double) As Double
deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts radians to decimal degrees :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function rad2deg(ByVal rad As Double) As Double
rad2deg = CDbl(rad * 180 / pi)
End Function

End Class
 
M

m.posseth

Well unless you are running the proggy on a MP systems multithreading will
make your proggy only slower

some tips to improve speed :

use the smallest possible datatype
use as less loops as possible and break out when possible
use the compiler optimization ( this can speed up calcs by 20% ) however
use it only if you know that a overflow will not occur in your situation
use as less "Try catch statements as possible " it is better to check a
result and return a value as to rely on a error to occur and then return a
value ( this costs much more as the latter ) try catch statements are verry
costly so use them only if you have no other option

do not use doevents !! if you need to repaint a progressbar , label etc
use the refresh / update method of the control

regards

Michel Posseth [MCP]





Scott Emick said:
I am using the following to compute distances between two lat/long
coordinates for a store locator - (VB .NET 2003)

it seems to take a long time to iterate through like 100-150 locations -
about 10-15 seconds...I want to make the code faster. I changed it to be
multi-threaded, and it doesn't really make it any faster. The bottleneck
seems to be with the math computations.

Any ideas like changing my data types or other ideas etc would be helpful.

Thanks,

--
Scott Emick
Web Programmer
Fox International
Remove the ham from mail address if it's not spam



Option Strict On
Imports System.Threading
Imports Infragistics.Shared
Imports Infragistics.Win
Imports Infragistics.Win.UltraWinGrid

Public Class Locator
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
[...]
#End Region

Public Q As New Queue
Public R As New Queue
Shared rwl As New ReaderWriterLock
Dim dvZip As DataView
Dim srcLat As Double
Dim srcLon As Double
Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFind.Click
dvZip = New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim deg As Double
Dim min As Double
Dim sec As Double
dvZip.RowFilter = "ZCODE='" & Microsoft.VisualBasic.Left(txtZip.Text,
5) & "'"

srcLat = CDbl(dvZip(0)("lat"))

srcLon = CDbl(dvZip(0)("lon"))
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow /
DsMM1.Mailing_Master.Count) * 100)
Application.DoEvents()
Q.Enqueue(mmrow)
R.Enqueue(currow)
Dim job3 As New ThreadStart(AddressOf ComputeDistance)
Dim thread3 As New Thread(job3)

thread3.Name = "ComputeDistance"
Do Until R.Count < 20
Loop
thread3.Start()
Next
Dim dvMM01 As New DataView(DsMM1.Mailing_Master)
UltraGrid1.DataSource = dvMM01
dvMM01.Sort = "distance"
dvMM01.RowFilter = "distance<=" & txtMiles.Text
Dim band As UltraGridBand = Me.UltraGrid1.DisplayLayout.Bands(0)
band.Columns("distance").SortIndicator = SortIndicator.Ascending
band.SortedColumns.Add("distance", False, False)
End Sub
Private Sub ComputeDistance()
Dim mmr As dsMM.Mailing_MasterRow = CType(Q.Dequeue,
dsMM.Mailing_MasterRow)
Dim lat As Double
Dim lon As Double
Dim dist As Integer
Dim dvZip2 As New DataView(DsMM1.Zip)
dvZip2.RowFilter = "ZCODE='" & Mid(mmr.MMZIP, 1, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip2(0)("lat"))
lon = CDbl(dvZip2(0)("lon"))
dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
Console.WriteLine(dist)
rwl.AcquireWriterLock(60000)
mmr.Distance = dist
rwl.ReleaseWriterLock()
Else
dist = 2147483647
End If
R.Dequeue()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Show()
txtResults.Text &= "Filling location database..." & vbCrLf
Application.DoEvents()
DsMM1.EnforceConstraints = False
daMM.Fill(DsMM1)
DsMM1.WriteXml("c:\dsmm1.xml")

daZip.Fill(DsMM1)
txtResults.Text &= "Enabling Constraints." & vbCrLf
Try
DsMM1.EnforceConstraints = True
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK)
End
End Try
txtResults.Text &= DsMM1.Mailing_Master.Count.ToString & " locations
available. " & vbCrLf
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Dim dvZip As New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim lat As Double
Dim lon As Double
Dim deg As Double
Dim min As Double
Dim sec As Double
Dim dist As Integer
Dim srcLat As Double
Dim srcLon As Double
'dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(txtZip.Text, 5) & "'"
'zlat = CStr(dvZip(0)("zlat"))
'deg = CDec(zlat.Substring(0, 2))
'min = CDec(zlat.Substring(2, 2))
'sec = CDec(zlat.Substring(4, 2))
'srcLat = deg + (min / 60) + (sec / 3600)
'zlon = CStr(dvZip(0)("zlon"))
'deg = CDec(zlon.Substring(0, 2))
'min = CDec(zlon.Substring(2, 2))
'sec = CDec(zlon.Substring(4, 2))
'srcLon = deg + (min / 60) + (sec / 3600)
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow / DsMM1.Zip.Count) * 100)
Application.DoEvents()
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(mmrow.MMZIP, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip(0)("LAT"))
mmrow.LAT = CDec(lat)
lon = CDbl(dvZip(0)("LON"))
mmrow.LON = CDec(lon)
daMM.Update(DsMM1.Mailing_Master)
'dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon,
"N")
mmrow.Distance = dist
Else
dist = 2147483647
End If
Next

End Sub
End Class


'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String)
As Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))
dist = CDbl(rad2deg(dist))
distance = CInt(dist * 60 * 1.1515)
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
If Abs(CDec(rad)) <> 1 Then
acos = pi / 2 - Atan(rad / Sqrt(1 - rad * rad))
ElseIf rad = -1 Then
acos = pi
End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts decimal degrees to radians :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function deg2rad(ByVal deg As Double) As Double
deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts radians to decimal degrees :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function rad2deg(ByVal rad As Double) As Double
rad2deg = CDbl(rad * 180 / pi)
End Function

End Class
 
J

Jim Underwood

I may be missing something, but it seems to me that calculating the distance
between two long/lat coordinates should take milliseconds. 150 calculations
should be done in under a second.

How long is the database query itself taking to return the rows?

Try running a stripped down version of the code, removing everything except
the select and the calculation. Take out all the multithreading, progress
bar, do events, etc. Limit it to:
Select some data from table
for each record in table
console.writeline(calcdistance)
next

See how long the code takes to run like this. I suspect it will be very
fast. Once the barbones calc is running reasonably fast, you can start
adding other pieces back in to see what is slowing you down.


Scott Emick said:
I am using the following to compute distances between two lat/long
coordinates for a store locator - (VB .NET 2003)

it seems to take a long time to iterate through like 100-150 locations -
about 10-15 seconds...I want to make the code faster. I changed it to be
multi-threaded, and it doesn't really make it any faster. The bottleneck
seems to be with the math computations.

Any ideas like changing my data types or other ideas etc would be helpful.

Thanks,

--
Scott Emick
Web Programmer
Fox International
Remove the ham from mail address if it's not spam



Option Strict On
Imports System.Threading
Imports Infragistics.Shared
Imports Infragistics.Win
Imports Infragistics.Win.UltraWinGrid

Public Class Locator
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
[...]
#End Region

Public Q As New Queue
Public R As New Queue
Shared rwl As New ReaderWriterLock
Dim dvZip As DataView
Dim srcLat As Double
Dim srcLon As Double
Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFind.Click
dvZip = New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim deg As Double
Dim min As Double
Dim sec As Double
dvZip.RowFilter = "ZCODE='" & Microsoft.VisualBasic.Left(txtZip.Text,
5) & "'"

srcLat = CDbl(dvZip(0)("lat"))

srcLon = CDbl(dvZip(0)("lon"))
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow /
DsMM1.Mailing_Master.Count) * 100)
Application.DoEvents()
Q.Enqueue(mmrow)
R.Enqueue(currow)
Dim job3 As New ThreadStart(AddressOf ComputeDistance)
Dim thread3 As New Thread(job3)

thread3.Name = "ComputeDistance"
Do Until R.Count < 20
Loop
thread3.Start()
Next
Dim dvMM01 As New DataView(DsMM1.Mailing_Master)
UltraGrid1.DataSource = dvMM01
dvMM01.Sort = "distance"
dvMM01.RowFilter = "distance<=" & txtMiles.Text
Dim band As UltraGridBand = Me.UltraGrid1.DisplayLayout.Bands(0)
band.Columns("distance").SortIndicator = SortIndicator.Ascending
band.SortedColumns.Add("distance", False, False)
End Sub
Private Sub ComputeDistance()
Dim mmr As dsMM.Mailing_MasterRow = CType(Q.Dequeue,
dsMM.Mailing_MasterRow)
Dim lat As Double
Dim lon As Double
Dim dist As Integer
Dim dvZip2 As New DataView(DsMM1.Zip)
dvZip2.RowFilter = "ZCODE='" & Mid(mmr.MMZIP, 1, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip2(0)("lat"))
lon = CDbl(dvZip2(0)("lon"))
dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
Console.WriteLine(dist)
rwl.AcquireWriterLock(60000)
mmr.Distance = dist
rwl.ReleaseWriterLock()
Else
dist = 2147483647
End If
R.Dequeue()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Show()
txtResults.Text &= "Filling location database..." & vbCrLf
Application.DoEvents()
DsMM1.EnforceConstraints = False
daMM.Fill(DsMM1)
DsMM1.WriteXml("c:\dsmm1.xml")

daZip.Fill(DsMM1)
txtResults.Text &= "Enabling Constraints." & vbCrLf
Try
DsMM1.EnforceConstraints = True
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK)
End
End Try
txtResults.Text &= DsMM1.Mailing_Master.Count.ToString & " locations
available. " & vbCrLf
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Dim dvZip As New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim lat As Double
Dim lon As Double
Dim deg As Double
Dim min As Double
Dim sec As Double
Dim dist As Integer
Dim srcLat As Double
Dim srcLon As Double
'dvZip.RowFilter = "ZCODE='" & Microsoft.VisualBasic.Left(txtZip.Text,
5) & "'"
'zlat = CStr(dvZip(0)("zlat"))
'deg = CDec(zlat.Substring(0, 2))
'min = CDec(zlat.Substring(2, 2))
'sec = CDec(zlat.Substring(4, 2))
'srcLat = deg + (min / 60) + (sec / 3600)
'zlon = CStr(dvZip(0)("zlon"))
'deg = CDec(zlon.Substring(0, 2))
'min = CDec(zlon.Substring(2, 2))
'sec = CDec(zlon.Substring(4, 2))
'srcLon = deg + (min / 60) + (sec / 3600)
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow / DsMM1.Zip.Count) * 100)
Application.DoEvents()
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(mmrow.MMZIP, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip(0)("LAT"))
mmrow.LAT = CDec(lat)
lon = CDbl(dvZip(0)("LON"))
mmrow.LON = CDec(lon)
daMM.Update(DsMM1.Mailing_Master)
'dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
mmrow.Distance = dist
Else
dist = 2147483647
End If
Next

End Sub
End Class


'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String) As
Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))
dist = CDbl(rad2deg(dist))
distance = CInt(dist * 60 * 1.1515)
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
If Abs(CDec(rad)) <> 1 Then
acos = pi / 2 - Atan(rad / Sqrt(1 - rad * rad))
ElseIf rad = -1 Then
acos = pi
End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts decimal degrees to radians :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function deg2rad(ByVal deg As Double) As Double
deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts radians to decimal degrees :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function rad2deg(ByVal rad As Double) As Double
rad2deg = CDbl(rad * 180 / pi)
End Function

End Class
 
A

Andrew Morton

'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931

What's wrong with Math.Pi ?
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String)
As Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))

But they're already doubles - take out all the CDbl() to make it more
readable. And maybe convert the angles to radians before even starting that
calculation.
distance = CInt(dist * 60 * 1.1515)

So, why's the following code in there - you've just exited the function.
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function

Umm, if that code gets a chance to execute, what happens if UCase(unit) is
neither "K" nor "N"?

const deg2rad as double=pi/180
const rad2deg as double=180/pi
' convert to radians
lat1=lat1*deg2rad
lat2=lat2*deg2rad
' find angle between coordinates
dist= acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos((lon2-lon1))*deg2rad)
select case UCase(unit)
case("K")
' return as kilometres???
distance=int(dist*60*1.1515*1.609344*rad2deg)
case("N")
' return as nautical miles???
distance=int(dist*60*1.1515*0.8684*rad2deg)
case else
' default to (statute?) miles???
distance=int(dist*60*1.1515*rad2deg)
end select

You forgot to put in comments as to what your constants 1.1515 etc.
represent. Maybe a comment that surface distance=radius*subtended angle
would be useful, seeing as you're using a variable named dist to represent
an angle.

I suspect your theta should be lon2-lon1, but since cos(x)=cos(-x) you're
not going to see any difference.

It may look neater to have deg2rad as a function, but if you're desperate
for faster code then write it in yourself (a quick look at the help didn't
suggest any way to in-line a function in VB.NET).
...
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
...

Don't you like Math.Acos() ?

Andrew
 
S

Scott Emick

Thanks - I do know to use the smallest datatype possible, but I need to
figure out just what that is for lat/long computations.

I am using doevents, so I will nix that in favor of the update/refresh for
my progress bar. The computations are occuring locally. I will also try
the compiler optimization as there should never be a divide by zero or bad
data problem.

Thanks very much all

Scott Emick


m.posseth said:
Well unless you are running the proggy on a MP systems multithreading will
make your proggy only slower

some tips to improve speed :

use the smallest possible datatype
use as less loops as possible and break out when possible
use the compiler optimization ( this can speed up calcs by 20% ) however
use it only if you know that a overflow will not occur in your situation
use as less "Try catch statements as possible " it is better to check a
result and return a value as to rely on a error to occur and then return a
value ( this costs much more as the latter ) try catch statements are
verry costly so use them only if you have no other option

do not use doevents !! if you need to repaint a progressbar , label etc
use the refresh / update method of the control

regards

Michel Posseth [MCP]





Scott Emick said:
I am using the following to compute distances between two lat/long
coordinates for a store locator - (VB .NET 2003)

it seems to take a long time to iterate through like 100-150 locations -
about 10-15 seconds...I want to make the code faster. I changed it to be
multi-threaded, and it doesn't really make it any faster. The bottleneck
seems to be with the math computations.

Any ideas like changing my data types or other ideas etc would be
helpful.

Thanks,

--
Scott Emick
Web Programmer
Fox International
Remove the ham from mail address if it's not spam



Option Strict On
Imports System.Threading
Imports Infragistics.Shared
Imports Infragistics.Win
Imports Infragistics.Win.UltraWinGrid

Public Class Locator
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
[...]
#End Region

Public Q As New Queue
Public R As New Queue
Shared rwl As New ReaderWriterLock
Dim dvZip As DataView
Dim srcLat As Double
Dim srcLon As Double
Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFind.Click
dvZip = New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim deg As Double
Dim min As Double
Dim sec As Double
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(txtZip.Text, 5) & "'"

srcLat = CDbl(dvZip(0)("lat"))

srcLon = CDbl(dvZip(0)("lon"))
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow /
DsMM1.Mailing_Master.Count) * 100)
Application.DoEvents()
Q.Enqueue(mmrow)
R.Enqueue(currow)
Dim job3 As New ThreadStart(AddressOf ComputeDistance)
Dim thread3 As New Thread(job3)

thread3.Name = "ComputeDistance"
Do Until R.Count < 20
Loop
thread3.Start()
Next
Dim dvMM01 As New DataView(DsMM1.Mailing_Master)
UltraGrid1.DataSource = dvMM01
dvMM01.Sort = "distance"
dvMM01.RowFilter = "distance<=" & txtMiles.Text
Dim band As UltraGridBand = Me.UltraGrid1.DisplayLayout.Bands(0)
band.Columns("distance").SortIndicator = SortIndicator.Ascending
band.SortedColumns.Add("distance", False, False)
End Sub
Private Sub ComputeDistance()
Dim mmr As dsMM.Mailing_MasterRow = CType(Q.Dequeue,
dsMM.Mailing_MasterRow)
Dim lat As Double
Dim lon As Double
Dim dist As Integer
Dim dvZip2 As New DataView(DsMM1.Zip)
dvZip2.RowFilter = "ZCODE='" & Mid(mmr.MMZIP, 1, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip2(0)("lat"))
lon = CDbl(dvZip2(0)("lon"))
dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
Console.WriteLine(dist)
rwl.AcquireWriterLock(60000)
mmr.Distance = dist
rwl.ReleaseWriterLock()
Else
dist = 2147483647
End If
R.Dequeue()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Show()
txtResults.Text &= "Filling location database..." & vbCrLf
Application.DoEvents()
DsMM1.EnforceConstraints = False
daMM.Fill(DsMM1)
DsMM1.WriteXml("c:\dsmm1.xml")

daZip.Fill(DsMM1)
txtResults.Text &= "Enabling Constraints." & vbCrLf
Try
DsMM1.EnforceConstraints = True
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK)
End
End Try
txtResults.Text &= DsMM1.Mailing_Master.Count.ToString & " locations
available. " & vbCrLf
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Dim dvZip As New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim lat As Double
Dim lon As Double
Dim deg As Double
Dim min As Double
Dim sec As Double
Dim dist As Integer
Dim srcLat As Double
Dim srcLon As Double
'dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(txtZip.Text, 5) & "'"
'zlat = CStr(dvZip(0)("zlat"))
'deg = CDec(zlat.Substring(0, 2))
'min = CDec(zlat.Substring(2, 2))
'sec = CDec(zlat.Substring(4, 2))
'srcLat = deg + (min / 60) + (sec / 3600)
'zlon = CStr(dvZip(0)("zlon"))
'deg = CDec(zlon.Substring(0, 2))
'min = CDec(zlon.Substring(2, 2))
'sec = CDec(zlon.Substring(4, 2))
'srcLon = deg + (min / 60) + (sec / 3600)
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow / DsMM1.Zip.Count) * 100)
Application.DoEvents()
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(mmrow.MMZIP, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip(0)("LAT"))
mmrow.LAT = CDec(lat)
lon = CDbl(dvZip(0)("LON"))
mmrow.LON = CDec(lon)
daMM.Update(DsMM1.Mailing_Master)
'dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon,
"N")
mmrow.Distance = dist
Else
dist = 2147483647
End If
Next

End Sub
End Class


'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String)
As Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))
dist = CDbl(rad2deg(dist))
distance = CInt(dist * 60 * 1.1515)
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
If Abs(CDec(rad)) <> 1 Then
acos = pi / 2 - Atan(rad / Sqrt(1 - rad * rad))
ElseIf rad = -1 Then
acos = pi
End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts decimal degrees to radians :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function deg2rad(ByVal deg As Double) As Double
deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts radians to decimal degrees :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function rad2deg(ByVal rad As Double) As Double
rad2deg = CDbl(rad * 180 / pi)
End Function

End Class
 
S

Scott Emick

I tried the optimization and remove integer overflow checks and that did
improve the speed somewhat. What was interesting to me was that removing
this following:

Const pi As Double = 3.1415926535897931

and simply using the .net framework's built in Pi make code execution about
30% faster.

All in all it is running much faster and smoother mostly due to:

1. Removing the application.doevents
2. Using the built-in Pi function

Thanks again,

Scott Emick
Software Engineer
Fox International


m.posseth said:
Well unless you are running the proggy on a MP systems multithreading will
make your proggy only slower

some tips to improve speed :

use the smallest possible datatype
use as less loops as possible and break out when possible
use the compiler optimization ( this can speed up calcs by 20% ) however
use it only if you know that a overflow will not occur in your situation
use as less "Try catch statements as possible " it is better to check a
result and return a value as to rely on a error to occur and then return a
value ( this costs much more as the latter ) try catch statements are
verry costly so use them only if you have no other option

do not use doevents !! if you need to repaint a progressbar , label etc
use the refresh / update method of the control

regards

Michel Posseth [MCP]





Scott Emick said:
I am using the following to compute distances between two lat/long
coordinates for a store locator - (VB .NET 2003)

it seems to take a long time to iterate through like 100-150 locations -
about 10-15 seconds...I want to make the code faster. I changed it to be
multi-threaded, and it doesn't really make it any faster. The bottleneck
seems to be with the math computations.

Any ideas like changing my data types or other ideas etc would be
helpful.

Thanks,

--
Scott Emick
Web Programmer
Fox International
Remove the ham from mail address if it's not spam



Option Strict On
Imports System.Threading
Imports Infragistics.Shared
Imports Infragistics.Win
Imports Infragistics.Win.UltraWinGrid

Public Class Locator
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
[...]
#End Region

Public Q As New Queue
Public R As New Queue
Shared rwl As New ReaderWriterLock
Dim dvZip As DataView
Dim srcLat As Double
Dim srcLon As Double
Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFind.Click
dvZip = New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim deg As Double
Dim min As Double
Dim sec As Double
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(txtZip.Text, 5) & "'"

srcLat = CDbl(dvZip(0)("lat"))

srcLon = CDbl(dvZip(0)("lon"))
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow /
DsMM1.Mailing_Master.Count) * 100)
Application.DoEvents()
Q.Enqueue(mmrow)
R.Enqueue(currow)
Dim job3 As New ThreadStart(AddressOf ComputeDistance)
Dim thread3 As New Thread(job3)

thread3.Name = "ComputeDistance"
Do Until R.Count < 20
Loop
thread3.Start()
Next
Dim dvMM01 As New DataView(DsMM1.Mailing_Master)
UltraGrid1.DataSource = dvMM01
dvMM01.Sort = "distance"
dvMM01.RowFilter = "distance<=" & txtMiles.Text
Dim band As UltraGridBand = Me.UltraGrid1.DisplayLayout.Bands(0)
band.Columns("distance").SortIndicator = SortIndicator.Ascending
band.SortedColumns.Add("distance", False, False)
End Sub
Private Sub ComputeDistance()
Dim mmr As dsMM.Mailing_MasterRow = CType(Q.Dequeue,
dsMM.Mailing_MasterRow)
Dim lat As Double
Dim lon As Double
Dim dist As Integer
Dim dvZip2 As New DataView(DsMM1.Zip)
dvZip2.RowFilter = "ZCODE='" & Mid(mmr.MMZIP, 1, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip2(0)("lat"))
lon = CDbl(dvZip2(0)("lon"))
dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon, "N")
Console.WriteLine(dist)
rwl.AcquireWriterLock(60000)
mmr.Distance = dist
rwl.ReleaseWriterLock()
Else
dist = 2147483647
End If
R.Dequeue()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Show()
txtResults.Text &= "Filling location database..." & vbCrLf
Application.DoEvents()
DsMM1.EnforceConstraints = False
daMM.Fill(DsMM1)
DsMM1.WriteXml("c:\dsmm1.xml")

daZip.Fill(DsMM1)
txtResults.Text &= "Enabling Constraints." & vbCrLf
Try
DsMM1.EnforceConstraints = True
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK)
End
End Try
txtResults.Text &= DsMM1.Mailing_Master.Count.ToString & " locations
available. " & vbCrLf
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Dim dvZip As New DataView(DsMM1.Zip)
Dim mmrow As dsMM.Mailing_MasterRow
Dim zlat As String
Dim zlon As String
Dim lat As Double
Dim lon As Double
Dim deg As Double
Dim min As Double
Dim sec As Double
Dim dist As Integer
Dim srcLat As Double
Dim srcLon As Double
'dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(txtZip.Text, 5) & "'"
'zlat = CStr(dvZip(0)("zlat"))
'deg = CDec(zlat.Substring(0, 2))
'min = CDec(zlat.Substring(2, 2))
'sec = CDec(zlat.Substring(4, 2))
'srcLat = deg + (min / 60) + (sec / 3600)
'zlon = CStr(dvZip(0)("zlon"))
'deg = CDec(zlon.Substring(0, 2))
'min = CDec(zlon.Substring(2, 2))
'sec = CDec(zlon.Substring(4, 2))
'srcLon = deg + (min / 60) + (sec / 3600)
Dim currow As Integer
For Each mmrow In DsMM1.Mailing_Master
currow += 1
UltraProgressBar1.Value = CInt((currow / DsMM1.Zip.Count) * 100)
Application.DoEvents()
dvZip.RowFilter = "ZCODE='" &
Microsoft.VisualBasic.Left(mmrow.MMZIP, 5) & "'"
If dvZip.Count > 0 Then
lat = CDbl(dvZip(0)("LAT"))
mmrow.LAT = CDec(lat)
lon = CDbl(dvZip(0)("LON"))
mmrow.LON = CDec(lon)
daMM.Update(DsMM1.Mailing_Master)
'dist = LocatorLib.Calcs.distance(srcLat, srcLon, lat, lon,
"N")
mmrow.Distance = dist
Else
dist = 2147483647
End If
Next

End Sub
End Class


'Below is from a class in a library project (dll)
Option Strict On
Imports System.Math
Public Class Calcs
Const pi As Double = 3.1415926535897931
Public Shared Function distance(ByVal lat1 As Double, ByVal lon1 As
Double, ByVal lat2 As Double, ByVal lon2 As Double, ByVal unit As String)
As Integer
Dim theta As Double, dist As Double
theta = lon1 - lon2
dist = Sin(CDbl(deg2rad(lat1))) * Sin(CDbl(deg2rad(lat2))) +
Cos(CDbl(deg2rad(lat1))) * Cos(CDbl(deg2rad(lat2))) *
Cos(CDbl(deg2rad(theta)))
dist = CDbl(acos(dist))
dist = CDbl(rad2deg(dist))
distance = CInt(dist * 60 * 1.1515)
Select Case UCase(unit)
Case "K"
distance = CInt(distance * 1.609344)
Case "N"
distance = CInt(distance * 0.8684)
End Select
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function get the arccos function from arctan function :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function acos(ByVal rad As Double) As Double
If Abs(CDec(rad)) <> 1 Then
acos = pi / 2 - Atan(rad / Sqrt(1 - rad * rad))
ElseIf rad = -1 Then
acos = pi
End If
End Function


'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts decimal degrees to radians :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function deg2rad(ByVal deg As Double) As Double
deg2rad = CDbl(deg * pi / 180)
End Function

'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'::: this function converts radians to decimal degrees :::
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Public Shared Function rad2deg(ByVal rad As Double) As Double
rad2deg = CDbl(rad * 180 / pi)
End Function

End Class
 
C

C-Services Holland b.v.

' return as kilometres???
distance=int(dist*60*1.1515*1.609344*rad2deg)

Another rather small optimisation is pre-solving all constant results
yourself beforehand like in this line.

distance=int(dist*60*1.1515*1.609344*rad2deg)

That could easily be replaced by

distance=int(dist*111.18957696*rad2deg)

Ofcourse it's just 2 multiplications you take out, but if it's
optimising you're looking for every bit helps :)
 
A

Andrew Morton

C-Services Holland b.v. said:
Another rather small optimisation is pre-solving all constant results
yourself beforehand like in this line.

distance=int(dist*60*1.1515*1.609344*rad2deg)

That could easily be replaced by

distance=int(dist*111.18957696*rad2deg)

Ofcourse it's just 2 multiplications you take out, but if it's
optimising you're looking for every bit helps :)

But that's part of the compiler's job, surely? And as rad2deg was defined as
a constant, it should do that product too.

Leaving the values individually editable helps when reading the code, or
editing it if, say, the mile is redefined.

Andrew
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top