W. Thomas Ofenstein and Kim A. Rauenzahn

Development of a MapObjects-Based Spatial Data Viewer and Analysis Tool for Remote Sensing Applications

April 1997

Remote Sensing markets, including precision agriculture, resource management, environmental monitoring, forestry and other related markets, require special-purpose tools for the display and analysis of relevant data. TASC has developed a spatial data viewer and analysis tool using MapObjects that enables a user to display multi-spectral imagery overlaid by vector data. The viewer was developed primarily with Visual Basic with some C++ to meet performance-critical requirements.


Introduction

Over the past two years TASC has been developing a remote sensing capability with application to precision agriculture, resource management, environmental monitoring, forestry and other related markets. Recently TASC announced an information service, emerge(tm), which provides value-added information products based on high-resolution, registered, multi-spectral mosaicked imagery. For the emerge service, this imagery has been enhanced for precision agriculture use. A principal output of the emerge service is a high-resolution mosaicked image of a grower's field. While growers are supplied hardcopy prints of the imagery, it was important to customers to have the ability to view the full resolution data with vector data layers (e.g., roads), providing contextual background information. While some growers already have access to agriculture-specific mapping tools, such as FarmWorks or AgLink, most growers have no capability for displaying the image data. The need to supply the growers with mapping capabilities for viewing our imagery has led to the development of the MapObjects-based emergeView.

Product Requirements and Capabilities

The basic requirements and goals for this product included:

While most of the technical requirements of the product could be achieved using Esri's ArcView product, the distribution costs for hundreds of potential customers led us to select MapObjects and Visual Basic as the development environment. This choice also gave us a flexible and powerful prototyping and development environment. As a starting point for the development, TASC selected the moView sample application as the basis for the emergeView graphical user environment.

The basic tool, as depicted below, provides the following capabilities:

emergeView Main Window

emergeView Main Window

The map layer "table of contents" is displayed in the Map Contents window as shown in the following picture. The Map Contents window provides the capabilities for adding new map and image layers, removing layers, defining the display order of layers, and turning layers off and on. The Properties button displays the Layer Properties window, which provides three rendering capabilities for vector data: single symbol, value map, and class breaks. A major enhancement of emergeView over moView is that the rendering properties for a layer are persistent for the emergeView session, and the Layer Properties window is displayed with the current rendering for the selected map layer.

Map Contents Window

Map Contents Window

An example of the Map Layer Properties window is shown below. The design of the tool is an enhanced version of the moView sample application. It has been upgraded to restore the symbolization of a previously symbolized map layer. The example below shows a class breaks definition. Some of the techniques for preserving and restoring the rendering are discussed later in the paper.

Map Layer Symbolization Window

Map Layer Symbolization Window

Special functionality was added to emergeView to allow customers to analyze high-resolution field imagery and tag crop scouting information to locations on the image. This capability uses a special map layer called a location layer, which is a specially attributed point shape file. A user can peruse images for locations of interest, tag a location and related textual information in the shape file, and print a report consisting of the locations and text data. The report can be used to locate these sites in the field with a GPS receiver. The last three tools on the main window toolbar and the last button on the button bar provide this functionality. The location layer capabilities include:

Two examples of textual outputs of the location tagging capability are shown below. The first example depicts the tabular view. Selecting a row in the table blinks the corresponding feature in the map display.

Location Layer Table Window

Location Layer Table Window

The second picture shows the textual version of location tagging. The information displayed in this window can be printed and used for scouting in the field. The geographic coordinates enable the grower or scout, using GPS, to go to the precise location identified by the printout.

Location Layer Text Window

Location Layer Text Window

Another important feature of emergeView is concept of a project file. The emergeView project file is similar in concept to the ArcView project file in that the user can save the current state of the session, and then restore that session at a later time. This includes not only the definition of the layers, but also the definition of the layer renderings, and any graphics or annotation added to the map. Some of the techniques for supporting project files are discussed below.

Selected Design Techniques

The complete design of emergeView is too extensive to be completely covered in this paper. Instead the following three selected design components will be discussed:

Coordinate Conversion

Early in the emergeproject, the project team determined that it was important to display our imagery in a projection system that could provide real ground measurements. To satisfy this, we decided to register our image products to the UTM projection. Consequently emergeView had to display image data in UTM coordinates. However, because growers work with GPS, it was also important to be able to display and tag data with geographic coordinates. Unlike ArcView, MapObjects does not support dynamic coordinate projection capabilities. Therefore, input image and vector data had to be in UTM coordinates, but a dynamic UTM-to-geographic conversion had to take place automatically as the cursor was moved in the map display area. TASC developed a UTM-to-geographic conversion utility in C++ as a Dynamic Link Library (DLL). We chose to do this conversion in C++ rather that Visual Basic because of the performance requirements of converting coordinates automatically as the cursor was moved (the MouseMove event).

emergeView Project Files

An important feature of any data display system is the ability to establish customized environmental settings (such as symbolization) within one session, save that session, and then restore that session at a later date. ArcView supports this concept with the ArcView project (.apr) file, emergeView similarly supports this with the emergeView (.evp) project file.

The following code sample illustrates the output of map and image layer information to the project file.

  ' output the layer information
  Dim theLayers As MapObjects.Layers 
  Set theLayers = mapDisp.Layers 
  Write #fileNum, theLayers.Count 

  ' output the layer information so that the display order is preserved on input 
  Dim i As Integer 
  For i = (theLayers.Count - 1) To 0 Step -1 
    Dim ndx As Integer 
    ndx = theLayers(i).Tag 
    Dim aLayerInfo As LayerInfo 

    ' get the layer information for this layer 
    Set aLayerInfo = colLayers(ndx) 

    ' output the layer path and file name 
    Write #fileNum, aLayerInfo.srcPath 
    Write #fileNum, aLayerInfo.srcFile 

    ' output the layer type (image or map) 
    Write #fileNum, aLayerInfo.layerType 

    ' output the layer visibility property 
    Write #fileNum, theLayers(i).Visible 

    ' if the layer is a map layer, output the rendering information
    If (theLayers(i).layerType = moMapLayer) Then 
      Write #fileNum, aLayerInfo.rendererStyle 

      ' output renderer-specific information
      Select Case aLayerInfo.rendererStyle 

        Case mvSSingleSymbol ' single symbol renderer 
          Call saveSingleSymbol(theLayers(i).symbol, fileNum) 

        Case mvSClassBreaks ' class breaks renderer 
          Call saveClassBreaks(theLayers(i).Renderer, fileNum) 

        Case mvSValueMap ' value map renderer 
          call saveValueMap(theLayers(i).Renderer, fileNum) 

      End Select 
    End If 
  Next i

An important part of generating the project file is maintaining information about each layer, including the type (map or image), the source, and the rendering style. This information has been encapsulated into the LayerInfo class.

The srcPath and srcFile components completely define the full path name of an image or map layer. This information must be captured when the layer is added to the map because it cannot be derived from the MO Map object after it has been added. The following code sample demonstrates the regeneration of the MapObjects layers from the project file.

  ' get the layers
  Dim cntLayers As Integer
  Input #fileNum, cntLayers
  Dim i As Integer
  For i = 1 To cntLayers
    Dim fileName As String
    Dim filePath As String
    Input #fileNum, filePath
    Input #fileNum, fileName
    Dim layerType As Integer
    Input #fileNum, layerType
    Dim vis As Boolean
    Input #fileNum, vis
    ' if this is a map layer, get the renderer inputs
    If (layerType = moMapLayer) Then
      If (Not addShapeLayer(filePath, fileName)) Then
        Close #fileNum
        On Error GoTo 0
        Exit Sub
      End If
      mapDisp.Layers(0).Visible = vis
      Dim rendererStyle As String
      Input #fileNum, rendererStyle
      Dim ndx As Integer
      ndx = mapDisp.Layers(0).Tag
      colLayers(ndx).rendererStyle = rendererStyle
      
      ' get the renderer-specific symbolization
      Select Case rendererStyle
      
        ' single symbol
        Case mvSSingleSymbol
          Set mapDisp.Layers(0).Renderer = Nothing
          Call openSingleSymbol(mapDisp.Layers(0).symbol, fileNum)
        
        Case mvSClassBreaks
          Set mapDisp.Layers(0).Renderer = New MapObjects.ClassBreaksRenderer
          Call openClassBreaks(mapDisp.Layers(0).Renderer, fileNum)
        
        Case mvSValueMap
          Set mapDisp.Layers(0).Renderer = New MapObjects.ValueMapRenderer
          Call openValueMap(mapDisp.Layers(0).Renderer, fileNum)
          
      End Select
      
    Else  ' image layer
      If (Not addImageLayer(filePath, fileName)) Then
        Close #fileNum
        On Error GoTo 0
        Exit Sub
      End If
      mapDisp.Layers(0).Visible = vis
    End If
  Next i

The following code sample is the subroutine saveSingleSymbol referenced above. This subroutine outputs the rendering information for a layer symbolized with a single symbol.

  Sub saveSingleSymbol(aSymbol As MapObjects.symbol, fileNum As Integer) 

    ' output all of the characteristics of the symbol
    With aSymbol 

      ' output the basic symbol characteristics 
      Write #fileNum, .SymbolType 
      Write #fileNum, .color 
      Write #fileNum, .Size 
      Write #fileNum, .style 

      ' output point symbol specific characteristics 
      If (.SymbolType = moPointSymbol) Then 
        With .Font 
          Write #fileNum, .Bold 
          Write #fileNum, .Italic 
          Write #fileNum, .name 
          Write #fileNum, .Underline 
        End With 
        Write #fileNum, .CharacterIndex 
        Write #fileNum, .Rotation 

      ' output fill symbol specific characteristics 
      ElseIf (.SymbolType = moFillSymbol) Then 
        Write #fileNum, .Outline 
        Write #fileNum, .OutlineColor 
      End If 
    End With 
  End Sub

The subroutine for regenerating the single symbol renderer follows. Note that intermediate variables sVal, iVal, and bVal must be used to input data from the project file because the symbol objects do not support direct assignment through file input in Visual Basic. While this is not a major problem, it does reduce the readability of the source code.

  Sub openSingleSymbol(aSymbol As MapObjects.symbol, fileNum As Integer)
    ' define intermediate variable for file input
    Dim sVal As String
    Dim lVal As Long
    Dim bVal As Boolean
    With aSymbol

      ' input general symbol characteristics
      Input #fileNum, lVal
      .SymbolType = lVal
      Input #fileNum, lVal
      .color = lVal
      Input #fileNum, lVal
      .Size = lVal
      Input #fileNum, lVal
      .style = lVal

      ' input point symbol specific characteristics
      If (.SymbolType = moPointSymbol) Then
        With .Font
          Input #fileNum, bVal
          .Bold = bVal
          Input #fileNum, bVal
          .Italic = bVal
          Input #fileNum, sVal
          .name = sVal
          Input #fileNum, bVal
          .Underline = bVal
        End With
        Input #fileNum, lVal
        .CharacterIndex = lVal
        Input #fileNum, lVal
        .Rotation = lVal

      ' input fill symbol specific characteristics
      ElseIf (.SymbolType = moFillSymbol) Then
        Input #fileNum, bVal
        .Outline = bVal
        Input #fileNum, lVal
        .OutlineColor = lVal
      End If
    End With
  End Sub

Map Layer Renderer Initialization

An important enhancement to the original moView sample application was the restoration of the renderer symbology for a map layer when the Layer Properties window was invoked. This section demonstrates how emergeView accomplishes this task following examples of the saving and regeneration of the single symbol renderer in the preceding section.

The single symbol option for a linear feature of the Layer Properties window is shown in the picture below. As depicted, the form provides the capability for the user to select a line style, line size (thickness), and line color. If this were a point symbol, the Other symbol properties button would provide further symbol definition capabilities.

Layer Properties Single Symbol Window

Layer Properties Single Symbol Window

The symbol initialization process for the single symbol renderer is accomplished with the following two subroutines. The first, singleSymbolInitRenderer, initializes the form and determines whether the map layer's current renderer is a single symbol renderer. If it is, then the form is initialized with the layer's current symbol; if not, then the form is initialized with a new random symbol.

  Public Sub singleSymbolInitRenderer()
    ' hide the controls not consistent with polygon symbolization
    If curFeatureType = moPolygon Then
      lblSingleSize.Visible = False
      txtSymbolSize.Visible = False
    End If

    ' if this is the current renderer, restore the symbol settings
    If (curRendererStyle = mvSSingleSymbol) Then
      Set curSymbol = curlayer.symbol
    Else
      Set curSymbol = New MapObjects.symbol
    End If

    ' initialize the list of symbol styles
    Call loadStyleCombo(cboSymbolStyle)

    ' initialize the form with the selected symbol
    Call singleSymbolCalc
  End Sub

The incorporation of the selected symbol is accomplished in the singleSymbolCalc subroutine, which is largely unchanged from moView, but is included for completeness.

  Public Sub singleSymbolCalc()
    Dim curStyleConst As Long

    picSymbolColor.BackColor = curSymbol.color
    txtSymbolSize.text = curSymbol.Size
    curStyleConst = curSymbol.style

    ' get the current style listed
    Dim strStyle As String
    Dim i As Integer
    strStyle = translateStyleConstant(curStyleConst)
    For i = 0 To (cboSymbolStyle.listCount - 1)
      If (cboSymbolStyle.List(i) = strStyle) Then
        cboSymbolStyle.ListIndex = i
        Exit For
      End If
    Next i
  
    ' display the symbol
    Set curDrawSymbol.symbol = curSymbol
    mapDrawSymbol.TrackingLayer.refresh True
    mapDrawSymbol.CopyMap 1
    imgSS.Picture = Clipboard.GetData
  End Sub

  Private Sub mapDrawSymbol_AfterTrackingLayerDraw(ByVal hDC As Long)
    ' draw the symbol
    curDrawSymbol.draw
  End Sub

As can be seen in the above code sample, the symbol displayed in the image control is actually generated in a hidden map control and copied into the image control. The variable curDrawSymbol is an instance of the class clsDrawSymbol. This class includes a method, draw, which renders the symbol into a map control. The draw method is invoked in the map control's AfterTrackingLayerDraw event.

Summary

The emergeView development effort has produced a desktop mapping tool that can display our customized multi-spectral imagery with vector background data. Our intent was to provide a basic, inexpensive capability to those customers not currently possessing commercial desktop mapping resources. The use of MapObjects greatly aided in the success of this development.

Acknowledgements

The authors would like to thank John Sawicki and Rob Comer of TASC for their contributions to the development of emergeView. John developed the Location Layer capability and Rob developed the C++ UTM-to-geographic conversion DLL. The authors would also like to acknowledge of the contributions of Michael Zeiler of Esri, the original author of moView, for the email exchanges that helped us to understand many of the moView design concepts. emerge is a trademark of TASC, Inc.


Author Information

W. Thomas Ofenstein
Principal MTS
TASC
55 Walkers Brook Drive
Reading, MA 01867
Telephone: (617)942-2000 x2192, (508)262-0656
Email: wtofenstein@tasc.com

Kim A. Rauenzahn
Manager, Spatial Technologies Section
TASC
55 Walkers Brook Drive
Reading, MA 01867
Telephone: (617)942-2000 x2411, (508)262-0668
Email: karauenzahn@tasc.com