MapWindow Script Directory

Script: ColorAndRenameLayers

Imports MapWindow.Interfaces
Imports MapWinGIS
Imports System
Imports System.Windows.Forms
Imports System.Collections
Imports Microsoft.VisualBasic
 
'Each script should (but doesn't have to) have a unique name. 
'Change MyExample here to something meaningful. ScriptMain should remain as "Main" however.

'***********************************************
'* Author: Paul Meems 7 feb 2006
'* This script renames the layernames
'* in the projectfile and gives all
'* shapes an unique color
'* Thanks to Chris Michaelis for helping me out
'* Paul Meems 13 november 2006
'* Added new function ColorByContiniousRamp,
'* which colors the shapefile using a color ramp
'***********************************************
Public Module ColorRenameLayers

    '***********************
    '* Main
    '***********************
    Public Sub ScriptMain(ByRef m_MapWin As IMapWin)
        Dim i As Long, handle As Long
        Dim fldIndex as Integer = 0 'Set this to the desired field
        Dim sStripString as string = "Martin-Test field total" 'this string is removed from the layername
        Dim bStep1 as Boolean = True ' I use this script twice, first step is to create        
          'unique colors, then I manually check all layers, next step is to create a continious ramp
          'and the *.mwsr file.
          
        '[PM 16 nov 2006]Due to remarks of Chris I've placed
        'm_MapWin.Layers.GetHandle(i) in place of just i in
        'calls to m_MapWin.Layers()        
        For i = 0 To m_MapWin.Layers.NumLayers - 1
            'get layer handle:
            handle = m_MapWin.Layers.GetHandle(i)
            'Rename layername in projectfile
            'm_MapWin.Layers(handle).Name = RenameLayername(m_MapWin.Layers(handle).Name)
            m_MapWin.Layers(handle).Name = RemoveStringInLayername(m_MapWin.Layers(handle).Name, sStripString)
            If bStep1 Then
              'Color layer with unique colors:
              ColorByUniqueBreaks(m_MapWin, fldIndex, handle)
            Else
              'Color with continious ramp:
              StartColorByContiniousRamp(m_MapWin, fldIndex, handle)
              'Create *.mwsr file:
              If Not m_MapWin.Layers(handle).SaveShapeLayerProps() Then
                MsgBox ("Could not create *.mwsr for " & m_MapWin.Layers(handle).Name)
              End If
            End If
        Next i
        MsgBox ("Ready")
    End Sub

    '***********************
    '* RenameLayername
    '***********************
    Private Function RenameLayername(ByVal sLayername As String) As String
        Dim arrTemp() As String

        arrTemp = sLayername.Split(" ")
        If (arrTemp.GetUpperBound(0) > 0) Then
            sLayername = arrTemp(arrTemp.GetUpperBound(0))
        End If
        Return sLayername
    End Function

    '***********************
    '* RenameLayername
    '***********************
    Private Function RemoveStringInLayername(ByVal sLayername As String, ByVal sStripString as String) As String

        sLayername = sLayername.Replace(sStripString, "")
        Return sLayername.Trim()
    End Function

    '***********************
    '* StartColorByContiniousRamp
    '***********************
    Sub StartColorByContiniousRamp(ByRef m_MapWin As IMapWin, ByVal fld As Integer, ByVal lyrNum As Integer)
        'Give each layer its own color ramp
        Dim usedColors As New Hashtable()
        Dim startColor, endColor As UInt32

        'Get the unique colors for this project:
        startColor = getRandomColor(usedColors)
        endColor = getRandomColor(usedColors)

        'Do the coloring
        ColorByContiniousRamp(m_MapWin, fld, lyrNum, startColor, endColor)

        'Clean up
        usedColors = Nothing
    End Sub
    '***********************
    '* ColorByContiniousRamp
    '***********************
    Private Function ColorByContiniousRamp(ByRef m_MapWin As IMapWin, ByVal fldIndex As Integer, ByVal lyrNum As Integer, ByRef ColorStart As UInt32, ByRef ColorEnd As UInt32) As Boolean
        Dim colorscheme As New MapWinGIS.ShapefileColorScheme()
        Dim colorbreak As New MapWinGIS.ShapefileColorBreak()
        Dim sf As MapWinGIS.Shapefile
        Dim fieldMin, fieldMax As Double

        'Get shapefile
        sf = CType(m_MapWin.Layers(lyrNum).GetObject, MapWinGIS.Shapefile)
        If sf Is Nothing Then Return False

        'Check input:
        If fldIndex > sf.NumFields - 1 OrElse fldIndex < 0 Then Return False

        If lyrNum > m_MapWin.Layers.NumLayers - 1 OrElse lyrNum < 0 Then Return False

        colorscheme.FieldIndex = fldIndex
        colorscheme.LayerHandle = lyrNum

        colorbreak.Caption = sf.Field(fldIndex).Name
        getMinMaxField(sf, fldIndex, fieldMin, fieldMax)
        'msgbox("fieldMin " & fieldMin & " fieldMax: " & fieldMax)

        colorbreak.StartValue = fieldMin
        colorbreak.startColor = ColorStart

        colorbreak.EndValue = fieldMax
        colorbreak.endColor = ColorEnd

        colorscheme.Add (colorbreak)

        'Set outlinecolor to black
        m_MapWin.Layers(lyrNum).OutlineColor = System.Drawing.Color.Black
        'Set fill color of layer to white, this is also the default fill color,
        'this should be done before attaching the color scheme:
        m_MapWin.Layers(lyrNum).Color = System.Drawing.Color.White

        'Attach colorscheme to layer:
        m_MapWin.Layers(lyrNum).ColoringScheme = colorscheme

        'Clean up:
        sf = Nothing
        colorscheme = Nothing
        colorbreak = Nothing


    End Function

    '***********************
    '* getMinMaxField
    '***********************
    Sub getMinMaxField(ByRef sf As MapWinGIS.Shapefile, ByRef fldIndex As Integer, ByRef fieldMin As Double, ByRef fieldMax As Double)
        'Loop trough all values of the field and determin the min and max
        Dim i As Integer
        Dim val As Double

        'init:
        fieldMin = 10000000
        fieldMax = -1000000
        Try
          For i = 0 To sf.NumShapes - 1
              val = sf.CellValue(fldIndex, i)
              If val < fieldMin Then fieldMin = val
              If val > fieldMax Then fieldMax = val
          Next i
        Catch lEx As Exception
          MsgBox ("Exception " & lEx.ToString)
        End Try

    End Sub

    '***********************
    '* ColorByUniqueBreaks
    '***********************
    Private Function ColorByUniqueBreaks(ByRef m_MapWin As IMapWin, ByVal fld As Integer, ByVal lyrNum As Integer) As Boolean
        Dim m_ColoringScheme As New MapWinGIS.ShapefileColorScheme
        Dim i As Integer
        Dim ht As New Hashtable()
        Dim sf As MapWinGIS.Shapefile
        Dim val As Object
        Dim arr() As Object
        'Dim tPrecision As Integer is never used.

        'Get shapefile
        sf = CType(m_MapWin.Layers(lyrNum).GetObject, MapWinGIS.Shapefile)
        If sf Is Nothing Then
            Return False
        End If

        'Check input:
        If fld > sf.NumFields - 1 OrElse fld < 0 Then
            Return False
        End If
        If lyrNum > m_MapWin.Layers.NumLayers - 1 OrElse lyrNum < 0 Then
            Return False
        End If

        'Remove current colors:
        While m_ColoringScheme.NumBreaks > 0
            m_ColoringScheme.Remove (0)
        End While

        'Get unique values
        For i = 0 To sf.NumShapes - 1
            val = sf.CellValue(fld, i)
            If Not ht.ContainsKey(val) Then
                ht.Add(val, val)
            End If
        Next i

        'Create sorted array:
        ReDim arr(ht.Count - 1)
        ht.Values().CopyTo(arr, 0)
        Array.Sort(arr)

        'Create color for each unique value
        For i = 0 To arr.length - 1
            Dim brk As New MapWinGIS.ShapefileColorBreak
            Dim randomColor As UInt32
            Dim usedColors As New Hashtable

            'because the coloring is randomly chosen, it's possible (and happens often) that
            'the same color is chosen twice.
            'Beacuse of this I save the colors per scheme to avoid this.
            randomColor = getRandomColor(usedColors)

            brk.startColor = randomColor
            brk.endColor = randomColor
            brk.StartValue = arr(i)
            brk.EndValue = arr(i)
            If IsNumeric(arr(i)) Then
                brk.Caption = CDbl(arr(i)).ToString("G3") 'G3 == format string
            Else
                brk.Caption = CStr(arr(i))
            End If

            'the field value to color by
            m_ColoringScheme.FieldIndex = fld
            m_ColoringScheme.Add (brk)
            brk = Nothing
            usedColors = Nothing
        Next i

        'Clean up:
        ht = Nothing
        sf = Nothing

        'Set outlinecolor to black
        m_MapWin.Layers(lyrNum).OutlineColor = System.Drawing.Color.Black
        'Set fill color of layer to white, this is also the default fill color,
        'this should be done before attaching the color scheme:
        m_MapWin.Layers(lyrNum).Color = System.Drawing.Color.White

        'Attach colorscheme to layer:
        m_MapWin.Layers(lyrNum).ColoringScheme = m_ColoringScheme
        Return True

    End Function

    '***********************
    '* getRandomColor
    '***********************
    Function getRandomColor(ByRef usedColors As Hashtable) As UInt32
        Dim randomColor As UInt32
        Dim webSafeColor As String
        Dim r, g, b As Integer

        'because the coloring is randomly chosen, it's possible (and happens often) that
        'the same color is chosen twice.
        'Beacuse of this I save the colors per scheme to avoid this.
        'I want nice contrasting colors so I save the websafe colorvalues so I don't get
        'for example several shades of lightgreen.

        r = CInt(Rnd() * 255)
        g = CInt(Rnd() * 255)
        b = CInt(Rnd() * 255)
        webSafeColor = Hex(r).Substring(0, 1) & Hex(g).Substring(0, 1) & Hex(b).Substring(0, 1)
        randomColor = System.Convert.ToUInt32(RGB(r, g, b))
        Do While usedColors.ContainsKey(webSafeColor)
            r = CInt(Rnd() * 255)
            g = CInt(Rnd() * 255)
            b = CInt(Rnd() * 255)
            webSafeColor = Hex(r).Substring(0, 1) & Hex(g).Substring(0, 1) & Hex(b).Substring(0, 1)
            randomColor = System.Convert.ToUInt32(RGB(r, g, b))
        Loop
        usedColors.Add(webSafeColor, webSafeColor)

        Return randomColor
    End Function

End Module


Back