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 8 3228
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" <se****@ham.fox-international.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl... 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
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" <se****@ham.fox-international.com> schreef in bericht
news:%2****************@tk2msftngp13.phx.gbl... 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
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" <se****@ham.fox-international.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl... 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
"Scott Emick" wrote '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
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" <po*****@planet.nl> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl... 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" <se****@ham.fox-international.com> schreef in bericht news:%2****************@tk2msftngp13.phx.gbl...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
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" <po*****@planet.nl> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl... 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" <se****@ham.fox-international.com> schreef in bericht news:%2****************@tk2msftngp13.phx.gbl...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
> ' 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 :)
--
Rinze van Huizen
C-Services Holland b.v
C-Services Holland b.v. wrote: ' 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 :)
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: hasadh |
last post by:
Hi,
is the assemly code for if..else and switch statements similar. I
would like to know if switch also uses value comparison for each case
internally or does it
jump to the case directly at...
|
by: Henrik Andersen |
last post by:
Hi newsgroup
Does the c++ compiler generate faster code at execution time than the C#
compiler?
Does the c++ compiler have more optimisations than the C# compiler?
Thanks in advance!
|
by: jesper |
last post by:
I would like some feedback on this.
A while back I was trying my hand at some pathfinding for a small game
I was making.
I did not know anything about it so I read some stuff and came up with
the...
|
by: Dave |
last post by:
I'm never quite sure whether to use "this." or not when referring to fields
or properties in the same class. It obviously works just fine without it
but sometimes I wonder if using this....
|
by: Extremest |
last post by:
I know there are ways to make this a lot faster. Any
newsreader does this in seconds. I don't know how they do
it and I am very new to c#. If anyone knows a faster way
please let me know. All...
|
by: Wisgary |
last post by:
I'm doing some benchmarking tests to compare Microsoft's CLR against
Mono's CLR. I could use some suggestions for how to objectively
compare the code. To my surprise the few tests I've run so far...
|
by: vunet.us |
last post by:
Is there a suggestion I can make this code run faster:
if(document.getElementById("1")){ doOne(); }
if(document.getElementById("2")){ doTwo(); }
.......................
|
by: Python Maniac |
last post by:
I am new to Python however I would like some feedback from those who
know more about Python than I do at this time.
def scrambleLine(line):
s = ''
for c in line:
s += chr(ord(c) | 0x80)...
|
by: Alpha83 |
last post by:
Hi,
Is there a code measuring tool that tells you which is more efficient
cost-wise. For example, if I were to compare the following two
identical code blocks, how do I know, which is more...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
| |