阅读:1024回复:1
Find Close Matches with MapX SearchEx Feature
MapInfo's "MapX" Active X product is a robust mapping control. The SearchEx method allows for the return of a collection of "close match" objects in the case of a non-exact match being made during a search. Input parameters required by the method are the search layer, search string and optional refining (boundary) layer. As a result of the search method several properties are set reporting the results of the find operation.
Let's get our hands dirty and look at some code to see all this in action. Here is an advanced "find" function making use of the new features: Here are a couple of examples: Example 1: Private Sub cmdAdvFind_Click() Dim FoundObj As MapXLib.FindResults Dim RefineFoundObj As MapXLib.FindFeature Dim FindLyr As MapXLib.Layer 'The layer to search within Set FindLyr = Map1.Layers("Nsw_lo") 'Setup find layer parameters FindLyr.Find.ClosestAddr = False FindLyr.Find.CloseMatchMax = 75 'Execute the search, "txtFind" is the variable we are looking for Set FoundObj = FindLyr.Find.SearchEx(txtFind) 'Check results of search If FoundObj.ExactMatch Then 'match has been made, adjust Map properties Map1.ZoomTo 39, FoundObj.MatchedFeature.CenterX, FoundObj.MatchedFeature.CenterY 'make found point the current selection Map1.Layers("Nsw_lo").Selection.SelectByPoint FoundObj.MatchedFeature.CenterX, FoundObj.MatchedFeature.CenterY, miSelectionNew Else 'Exact match not found, dump data into seperate form frmCloseM.List1.Clear 'Cycle thru and add features in found collection to List box i = FoundObj.Matches.Count For n = 1 To i frmCloseM.List1.AddItem FoundObj.Matches.Item(n).Name + " (" + Str(FoundObj.Matches.Item(n).Score) + "%)" Next 'display seperate form frmCloseM.Show 1 ' "intrefine" is a (global) variable used to hold the position of the selected object 'for this purpose the position is held as the listbox index. If the cancel button 'was pressed then the variable is set to be -99 If (intrefine + 1) >= 1 Then 'this code only executed if a valid selection is made 'this time use the Search method as the selection has been made from only 'valid objects Set RefineFoundObj = FindLyr.Find.Search(FoundObj.Matches.Item(intrefine + 1).Name) 'assume a match as the search text has in effect already been parsed, therefore 'adjust map properties accordingly Map1.ZoomTo 39, RefineFoundObj.CenterX, RefineFoundObj.CenterY 'make found point the current selection Map1.Layers("Nsw_lo").Selection.SelectByPoint RefineFoundObj.CenterX, RefineFoundObj.CenterY, miSelectionNew End If End If End Sub The basic methodology used for this application was to prompt the User for a search string in the case of the initial search (refer Figure 1). This is then passed to the search engine which returns a found object, in the code above a search is being made on a town name only, so we have no refining boundary. If an exact match is made then the map properties are adjusted accordingly to reflect the position of the found object. The status of whether an exact match has been made is easily queried by checking the "exact match" property, a boolean set by the search method ![]() In the case of a non-exact match being made the User is then presented with a list of "close matches" and asked to pick the appropriate entry (refer Figure 2). The list of close matches also displays the match "score" a percentage figure indicates the degree of match that has been made (100 = exact match, 0 = no match). Once the User has chosen a final selection from the list, the returned object then becomes the search string in a second search, this time using the Search method. In effect allowing the User to choose from existing choices parses the data, all the choices in the list are objects within the search layer, thus the second time around a successful search is guaranteed. Once a successful match has been made then the appropriate Map properties are altered to adjust the zoom and centre properties of the map as appropriate. A global variable "intrefine" is used to pass the index of list box item back to the main form, setting this variable to a invalid number (i.e. < 0) can also be used as a tag to indicate the cancel button has been chosen. ![]() |
|
1楼#
发布于:2003-12-08 09:27
The result for this application, is a significantly enhanced find function that is more User friendly when an exact match cannot be made. Further, on a broader perspective, the improved feature adds flexibility for Developers when building applications that incorporate any find functionality.
Example 2: Let抯 walk through an example of SearchEx where we want to find a city in the United States. We will use files that ship with MapX 3.5.2 (US geoset), Microsoft VisualBasic v6.0 and the Microsoft FlexGrid Control 6.0. Step 1: The setup. In order to perform a find, you must set the defaults on the Find Object to tell it which layers, datasets, and fields you would like MapX to search. In this example, the city layer (US Major Cities) is the primary layer and the state layer (USA) is the refining layer. Public Sub SearchEx(txtCity As String, txtState As String) Dim lyrCity As Layer Dim dsCity As Dataset Dim dsState As Dataset Dim objFindResults As FindResults Dim intNumCols As Integer Dim intNumRows As Integer Dim counter As Integer Dim firstcounter As Integer Set lyrCity = Map1.Layers("US Major Cities") 'This file ships as sample data with MapX. Set lyrState = Map1.Layers("USA") ' Add the datasets Set dsCity = Map1.Datasets.Add(miDataSetLayer, lyrCity) Set dsState = Map1.Datasets.Add(miDataSetLayer, lyrState) ' Set the city dataset to be the find dataset Set lyrCity.Find.FindDataset = dsCity Set lyrCity.Find.FindField = dsCity.Fields("city") ' Set the state dataset to be the refining dataset Set lyrCity.Find.RefineLayer = lyrState Set lyrCity.Find.RefineDataset = dsState Set lyrCity.Find.RefineField = dsState.Fields("state") Step 2: The find This is the easy part. You just need to call SearchEx with the city and state you would like to find. Set objFindResults = lyrCity.Find.SearchEx(txtCity, txtState) Step 3: The results Once the search has been performed, you need to determine if there were multiple matches found, and display them to the user. If multiple matches were found, you may want to use a multi-list box for the user to choose which of the matches, if any, he or she would like. If objFindResults.MultipleMatches = True Then ' Populate the List Box with multiple matches For Each objMatchCandidate In objFindResults.Matches firstcounter = firstcounter + 1 List1.AddItem objMatchCandidate.Name ' Populate the FlexGrid (multi-column layout) intNumRows = objFindResults.Matches.Count intNumCols = dsCity.Fields.Count CityGrid.Cols = intNumCols CityGrid.Rows = intNumRows For counter = 1 To intNumCols CityGrid.Row = firstcounter - 1 CityGrid.Col = counter - 1 CityGrid.Text = dsCity.Value(objMatchCandidate.FeatureID, counter) Next Next Else ' Populate the List Box with one match List1.AddItem objFindResults.MatchedFeature.Name intNumCols = dsCity.Fields.Count CityGrid.Cols = intNumCols ' Populate the FlexGrid For counter = 1 To intNumCols CityGrid.Col = counter - 1 CityGrid.Text = dsCity.Value(objFindResults.MatchedFeature.FeatureID, counter) Next End If End Sub Let抯 call this new subroutine two different ways. The first way, we抣l pass in a city and state where there is one known match: SearchEx "Springfield", "IL" Here are the results: ![]() Notice the List and FlexGrid display only one result, as expected. Now, calling SearchEx again, we only pass in the city parameter and leave the state parameter blank: SearchEx "Springfield", "" ![]() This search returns multiple results because there is more than one Springfield in the US Major Cities file. Try out SearchEx on other searches for addresses or features. For geographic searches, such as finding all school locations in a city boundary, use SearchWithinFeature, SearchWithinDistance, SearchWithinRectangle, or SearchAtPoint. To learn more about MapX and download a free trial version, go to www.mapx.com. |
|