' View.ZoneGeocode - Add a Geo Event Theme from an address table
' of ambiguous addresses with fuzzy zones.
'
' The address table requires two fields, Address and Zone. These
' must be able to be standardised accoring to the New Zealand
' standardisation rules vnz_addr.stn and nzplaces.stn respectively.
' (International users read "local standardisation rules" here)
' When an ambigous address is found, the zone value is used in
' an attempt to resolve the ambiguity. The geocoded theme has a
' field with concatenated route internal numbers (Zonelist). The
' candidate arcs for ambiguous addresses are searched for zones to
' which they belong (routes in the SBRB route system) and if one
' alone has an agreeing zone value (Zone = route Name) it becomes the
' matched candidate. Failures are resolved by the user picking one
' candidate by inspection on the screen.
'
' Bruce Harold, Eagle Technology, New Zealand, November 1995
'
' Get the match source and the event table to match.
theView = av.GetActiveDoc
roadFTab = theView.FindTheme("Road").GetFTab
routeFTab = FTab.Make((roadFTab.GetSrcname.GetDataSource++"route.sbrb").AsSrcName)
theMatchSource = theView.FindTheme("Road").GetMatchSource
evntTab = av.GetProject.FindDoc("Addresses").GetVTab
addrfld = evntTab.findField("Address")
'
' Create the match keys, match case and match preferences.
theMatchKey = MatchKey.Make(theMatchSource.GetStanRules)
theMatchKey.AllowIntersections("nz_intsc.stn","&")
nfields = theMatchKey.GetNumFields - 1
placeMatchKey = MatchKey.Make("nzplaces.stn")
theMatchCase = MatchCase.Make(theMatchSource, theMatchKey)
theMatchPref = MatchPref.Make
theMatchPref.SetPref(#matchpref_noreview,true)
theMatchPref.SetPref(#matchpref_minmatchscore,true)
theMatchPref.SetPrefVal(#matchpref_minmatchscore,50)
'
' Create the GeoName.
aGeoName = GeoName.Make(theMatchSource,evntTab,addrfld,nil)
'
' Initialise the GeoTheme
geoTheme = theMatchSource.InitGeoTheme(aGeoName)
'
numrecs = evntTab.GetNumRecords
'
av.SetStatus(0)
av.ShowMsg("Geocoding addresses...")
'
for each i in evntTab
'
av.SetStatus(i / evntTab.GetNumrecords * 100)
'
' Set next address to MatchKey key field.
theMatchKey.SetKey(evntTab.ReturnValueString(addrfld,i))
stanAddress = ""
for each i in 0..(nfields - 2) 'ignore soundex fields
stanAddress = stanAddress++theMatchKey
.GetValue(theMatchKey.GetNthField(i))++""
end
'
' Search for candidates.
numCand = theMatchSource.Search(theMatchKey,80,theMatchCase)
'
if (numCand = 0) then
theMatchSource.WriteUnMatch(i,theMatchKey)
continue
end
'
'Score the candidates
theMatchCase.ScoreCandidates
'
'Skip if no acceptable candidates
if (theMatchCase.GetBestCand.GetScore <
theMatchPref.GetPrefVal(#matchpref_minmatchscore)) then
continue
end
'
'If sole acceptable candidate, take it and continue
if (theMatchCase.GetNumCands = 1) then
theMatchSource.WriteMatch(i,theMatchKey,theMatchCase.GetBestCand)
continue
end
'
'Get the list of equal best candidates
bestscore = theMatchCase.GetBestCand.GetScore
candList = {}
for each c in 1..theMatchCase.GetNumCands
if (theMatchcase.GetNthCand(c).GetScore = bestscore) then
candList.Add(theMatchcase.GetNthCand(c))
end
end
'
'Standardise the given Zone
givenZone = evntTab.ReturnValue(evntTab.FindField("Zone"),i).Trim
placeMatchKey.SetKey(givenZone)
givenZone = placeMatchKey.GetValue(placeMatchKey.GetNthField(0))
if (givenZone = "") then 'unknown zone
'MsgBox.Warning("Given Zone"++
'evntTab.ReturnValue(evntTab.FindField("Zone"),i).Trim.Quote+nl+
'"for address:"++evntTab.ReturnValue(evntTab.FindField("Address"),i)+nl+
'"failed to standardise.","NZ Place Names Standardisation")
givenZone = evntTab.ReturnValue(evntTab.FindField("Zone"),i).Trim
end
'
'If many with best score see if one has a good Zone value.
favCand = nil
candSubList = {}
for each c in candList
arcrec = c.GetMatchSourceRec
zoneList = roadFTab.ReturnValue(roadFTab.FindField("Zonelist"),arcrec).Trim
.AsTokens(" ")
candSubList.Add(routeFtab.ReturnValue(routeFTab.FindField("Name"),
(zoneList.Get(0).AsNumber)-1))
for each z in zoneList
if (routeFtab.ReturnValue(routeFTab.FindField("Name"),z.AsNumber-1)
.Substitute(" ","") = givenZone) then
favCand = c
end
end
end
'
'Use the favourite Candidate if found
if ((favCand.Is(MatchCand)) or (candList.Count = 1)) then
if (candList.Count = 1) then favCand = candList.get(0)
end
theMatchSource.WriteMatch(i, theMatchKey, favCand)
continue
else 'Get the user to select a Candidate:
'Add graphics for each candidate
theGraphics = theView.GetGraphics
theGraphics.Empty
candRecList = {}
for each c in candList
candRecList.Add(c.GetMatchSourceRec)
candPoint = theMatchSource.GetPoint(c)
cGP = GraphicShape.Make(candPoint)
cGP.SetSymbol(av.GetSymbolWin.ReturnCurrentSymbol(#symbol_marker))
theGraphics.Add(cGP)
cGT = GraphicText.Make(candSubList.Get(candList.Find(c)),candPoint)
cGT.SetSymbol(av.GetSymbolWin.ReturnCurrentSymbol(#symbol_text))
theGraphics.Add(cGT)
end
'
'Choose a candidate by inspection, or Cancel to bail
candSubIndex = MsgBox.ListAsString(candSubList,"Choose the Suburb",stanAddress)
if (candSubIndex = nil) then
theMatchSource.WriteUnMatch(i,theMatchKey)
continue
end
theChosenCand = candRecList.Get(candSubList.Find(candSubIndex))
theGraphics.Empty
if (theChosenCand = nil) then
theMatchSource.WriteUnMatch(i,theMatchKey)
continue
end
for each c in candList
if (c.GetMatchSourceRec = theChosenCand) then
theChosenCand = c
end
end
if (theChosenCand.Is(MatchCand)) then
theMatchSource.WriteMatch(i,theMatchKey,theChosenCand)
continue
end
end
'
end
'
av.ClearStatus
av.ClearMsg
'
theMatchSource.EndMatch
'
' Add geocoded theme.
geoTheme = Theme.Make(aGeoName)
theView.AddTheme(geoTheme)
geoTheme.SetVisible(true)