gis1117
  • 注册日期
  • 发帖数
  • QQ
  • 铜币
  • 威望
  • 贡献值
  • 银元
阅读:971回复:1

Find Close Matches with MapX SearchEx Feature

楼主#
更多 发布于:2003-12-08 09:18
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.

喜欢0 评分0
gis1117
  • 注册日期
  • 发帖数
  • QQ
  • 铜币
  • 威望
  • 贡献值
  • 银元
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.

举报 回复(0) 喜欢(0)     评分
游客

返回顶部