ThinkGeo.com    |     Documentation    |     Premium Support

Applying Visual Style but correct color is not filled in shape

Hello,



I have Shape file of Pakistan and I am coloring the provinces based on number of projects. For this I have applied Visual Style and has given colors based on some criteria. It is loading the colors but not accordingly, it is loading at its own. Following is my code.




Dim objDatatable As DataTable
            Dim pkMapLayer As New CustomDataShapeFileFeatureLayer(Server.MapPath("~/Content/Shapes/PAK_adm1.shp"))
            objDatatable = GetThematicAreaWsProjects(lAreaID, lThematicAreaID)
            pkMapLayer.RequireIndex = False
            pkMapLayer.InitDictionaries("Area", objDatatable, "Colour_map")
 
            Dim valueStyle As New ValueStyle()
            valueStyle.ColumnName = "Colour_map"
            valueStyle.ValueItems.Add(New ValueItem("1", AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.LightPink, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem("2", AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 255, 79, 79), GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem("3", AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 255, 179, 79), GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem("4", AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.Red, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem("5", AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.RosyBrown, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem("6", AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.DarkRed, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem("Area", TextStyles.Country1("[Area]")))
            pkMapLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(valueStyle)
 
            pkMapLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
            Return pkMapLayer

 Where I have colour_map =1 , it is loading color for Value 4 i-e Red and same is the case for others. I need to resolve this asap.



Thanks in advance.



Naeem

Hi Naeem, 
  
 I hadn’t found you miss something in your code, because I cannot reproduced that only from your code.  
  
 For solve your issue, please upload a sample with data which can reproduced your issue, or provide a code sample based on the data in our sample. 
  
 Regards, 
  
 Don 


Thanks for your reply.



Do you need shape files, data associated with that and code to retrieve the data?



Best Regards,

Naeem

Following is the code which I am using.




<MapActionFilter()> _
       Function DrawThematicAreaWise(map As ThinkGeo.MapSuite.MvcEdition.Map, args As GeoCollection(Of Object), Optional lAreaID As Int32 = -1, Optional lThematicAreaID As Int32 = 1) As ActionResult
           Dim objMapClass As New MapModel
           If map Is Nothing Then
 
 
               map = New Map(“Map1”, New System.Web.UI.WebControls.Unit(100, System.Web.UI.WebControls.UnitType.Percentage), 510)
               map.CurrentExtent = New RectangleShape(70.4575022977941, 31.96396484375, 80.2297679227941, 20.36240234375)
               map.MapUnit = GeographyUnit.DecimalDegree

’This is here, I am calling the function to get the Custom Shape File layer the code already shared.

               usStatesLayer = GetCustomDataShapeFileFeatureLayerForThematic(lAreaID, lThematicAreaID)
               Dim TextLayer As New ShapeFileFeatureLayer(Server.MapPath("~/Content/Shapes/PAK_adm1.shp"))
               TextLayer.RequireIndex = False
               TextLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.City1
               TextLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.City1("[Abbr]")
               TextLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
 
               'Dim TextOverlay As New LayerOverlay()
               'TextOverlay.Layers.Add(“Names”, TextLayer)
               'TextOverlay.IsBaseOverlay = True
 
               Dim staticOverlay As New LayerOverlay()
 
               staticOverlay.Layers.Add(“Names”, TextLayer)
               staticOverlay.Layers.Add(“Cities”, usStatesLayer)
               staticOverlay.IsBaseOverlay = False
 
               map.AdornmentOverlay.Layers.Add(BuildLegendForThematic())
               map.CustomOverlays.Add(staticOverlay)
               'map.CustomOverlays.Add()
 
               objMapClass.map = map
               objMapClass.PageModel = lModel
           End If
           Return View(objMapClass)
       End Function

For Data I am using the following function.


Function GetThematicAreaWsProjects(Optional lAreaID As Int32 = -1, Optional lThematicAreaID As Int32 = 1) As DataTable
            Dim dataTabl As DataTable
 
            Dim lManager As New Manager(Me.SessionUser)
            lModel = lManager.GetThematicandAreaWiseProjects(lAreaID, lThematicAreaID)
            For Each Item As Models.ThematicandAreaWsProject In lModel.ThematicandAreaWsProjects
                Select Case Item.Total
                    Case 1 To 4
                        Item.Colour_map = 1
                    Case 4 To 6
                        Item.Colour_map = 2
                    Case 6 To 8
                        Item.Colour_map = 3
                    Case 8 To 10
                        Item.Colour_map = 4
                    Case 10 To 100
                        Item.Colour_map = 5
                End Select
            Next
            dataTabl = lManager.ConvertToDataTable(lModel.ThematicandAreaWsProjects.ToList)
            lManager.Dispose()
            lManager = Nothing
            Return dataTabl
        End Function

I hope this will help to sort out my issue. I am also attaching the screenshot for your review.



Thanks






Hi Naeem,  
  
 I think we also need your data. 
  
 Regards, 
  
 Don


Public Class ThematicandAreaWsProject
        Public Property Area As String
        Public Property ThematicArea As String
        Public Property AreaID As Int32
        Public Property ThematicAreaID As Int32
        Public Property Total As Integer
 
        Public Property Colour_map As Integer = 0
    End Class
    Public Class ThematicandAreaWiseProjectsModel
        Inherits PageModelBase
 
        Public Property SelectedAreaID As String
        Public Property SelectedThematicAreaID As String
 
        Public Property Areas As IEnumerable(Of LookUPItem)
        Public Property ThematicAreas As IEnumerable(Of LookUPItem)
 
        Public ThematicandAreaWsProjects As IEnumerable(Of ThematicandAreaWsProject)
        Public Sub New()
            MyBase.new()
        End Sub
    End Class



Now you may use the following data.



Area= "GB"

AreaID=1

Total:1



Area= "KP"

AreaID=2

Total:2



Area= "PAK"

AreaID=3

Total:1



Area= "FATA"

AreaID=4

Total:3



Area= "FCT"

AreaID=5

Total:1



Area= "Punjab"

AreaID=6

Total:1



Area= "Balochistan"

AreaID=7

Total:1



Area= "Sindh"

AreaID=8

Total:1



I can not here upload the Shape file.


Hi Naeem,  
          Can you send me shape files of pakistan map.

Hi Shehraz, 
  
 You may download the files from following link. 
  
 unocha.org/pakistan/maps-graphics/administrative-maps 
  
 Thanks, 
 Naeem

Hi Naeem,



I have two questions need to verify for your case:



1. I noticed you defined the ValueStyle for the pkMapLayer, but I didn’t noticed how you convert the DataTable data (from GetThematicAreaWsProjects method) into the pkMapLayer featuresSource. As you may know the value Style only works when the feature has the specified column name. 

2. I can see you are created a map instance in an action method  DrawThematicAreaWise. But I don’t think it will refresh automatically in the client side. In Mvc, the map instance only initialize one time when the page load and all the interactive operations between the client side and server side are through AjaxCall method. We can’t do a lot of changes on the server side in the mapping action in the server side, as every changes in the server side, we will need to refresh it in the client side at the callback method of AjaxCall. For instance, when we click the map, it will trigger an ajax call to the serve action, in the server action method, we add a marker into a layer. Then, in the ajaxcall callback, we need to refresh the marker layer to make the new marker show.



Another question is are your shapes shown on the map? or simply the shape are not colored?



If you still have some questions on your application, could you please attached more codes here so we can look into further?

Thanks,

Troy

Dear Troy,



Thanks for your message.



Answer to your questions.



Value Style is implemented and it is coloring the shapes. It is showing the shapes as well. But it is coloring wrong. If you see my second and third post in this thread you will have an idea. All is working fine except, it is giving different colors. Like if I want to color one province Dark Red, it is not coloring that province Dark Red, it will color some other province dark red.



Following is my code to convert datatable to Feature Source.




Public Sub InitDictionaries(linkFieldName As String, externalDataBase As DataTable, ParamArray customColumnNames As String())
            ShapeFileFeatureLayer.BuildRecordIdColumn(Me.ShapePathFileName, “ID_0”, BuildRecordIdMode.DoNotRebuild)
 
            FeatureSource.Open()
            Dim fileName As String = System.IO.Path.GetFileNameWithoutExtension(Me.ShapePathFileName)
            Dim dataTable As DataTable = FeatureSource.ExecuteQuery(String.Format(“select ID_0, {0} from {1}”, linkFieldName, fileName))
 
            For Each dataRow As DataRow In dataTable.Rows
                idLinkFieldDictionary.Add(dataRow(“ID_0”).ToString(), dataRow(linkFieldName).ToString())
            Next
            For Each customColumnName As String In customColumnNames
                Dim dictionary As New Dictionary(Of String, String)()
                ’ Here is you own code getting the dictionary from the LinkField To The customColumn you want
                ’ This sample is using DataTable as the external database. You can change it to consume your own databases.
                For Each dataRow As DataRow In externalDataBase.Rows
                    dictionary.Add(dataRow(linkFieldName).ToString(), dataRow(customColumnName).ToString())
                Next
                customFieldsDictionaries.Add(customColumnName, dictionary)
            Next
        End Sub

 For me everything is working fine, except it is coloring the shapes but not as I specified in my code.



I hope now you will have a better idea of my problem.



Thanks

Naeem







Hi Naeem,



Thanks for your verification, I got your question now.



Here is my thought: In order to make the value style works fine, difference column value will be mapping to difference defined style, we need to make sure the features has the specified column and its value. So, in your project, please check your pkMapLayer has "Colour_map" column. You can try the below codes after you initialize the pkMapLayer data:


pkMapLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
 
pkMapLayer.Open();
Collection<Feature> featurs = pkMapLayer.FeatureSource.GetAllFeaturs(ReturnALlColumn);
if(features.Any()){
    string value = features[0].ColumnValues["Colour_map"]
}
 
Return pkMapLayer

Another thought would be on your CustomDataShapeFileFeatureLayer, would you please attached how you defined this class?



Thanks,

Troy

Dear Troy,



Thanks for your reply. I am using following code to set the ValueStyle and in this I am assigning the Colour_map as well.




Dim objDatatable As DataTable
            Dim pkMapLayer As New CustomDataShapeFileFeatureLayer(Server.MapPath("~/Content/Shapes/PAK_adm1.shp"))
            objDatatable = GetThematicAreaWsProjects(lAreaID, lThematicAreaID)
            pkMapLayer.RequireIndex = False
            pkMapLayer.InitDictionaries(“Area”, objDatatable, “Colour_map”)
 
            Dim valueStyle As New ValueStyle()
            valueStyle.ColumnName = “Colour_map”
            valueStyle.ValueItems.Add(New ValueItem(“1”, AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.LightPink, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem(“2”, AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 255, 79, 79), GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem(“3”, AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 255, 179, 79), GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem(“4”, AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.Red, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem(“5”, AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.RosyBrown, GeoColor.StandardColors.Black)))
            valueStyle.ValueItems.Add(New ValueItem(“6”, AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.DarkRed, GeoColor.StandardColors.Black)))
            ‘valueStyle.ValueItems.Add(New ValueItem(“Area”, TextStyles.Country1("[Area]")))
            pkMapLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(valueStyle)
 
            pkMapLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
            Return pkMapLayer

I had added this in my first post as well. Following is the code which I am using for the class “CustomDataShapeFileFeatureLayer”.




Public Class CustomDataShapeFileFeatureLayer
        Inherits ShapeFileFeatureLayer
        Private idLinkFieldDictionary As New Dictionary(Of String, String)()
        Private customFieldsDictionaries As New Dictionary(Of String, Dictionary(Of String, String))()
 
        Private Sub New()
            Me.New(String.Empty)
        End Sub
 
        Public Sub New(shapeFileFilePath As String)
            MyBase.New(shapeFileFilePath)
            AddHandler FeatureSource.CustomColumnFetch, AddressOf FeatureSource_CustomColumnFetch
        End Sub
 
        ‘’’ <summary>
        ‘’’ Merge the datatable to the shape file layer.
        ‘’’ </summary>
        ‘’’ <param name=“linkFieldName”></param>
        ‘’’ <param name=“externalDataBase”></param>
        ‘’’ <param name=“customColumnNames”></param>
        Public Sub InitDictionaries(linkFieldName As String, externalDataBase As DataTable, ParamArray customColumnNames As String())
            ShapeFileFeatureLayer.BuildRecordIdColumn(Me.ShapePathFileName, “ID_0”, BuildRecordIdMode.DoNotRebuild)
 
            FeatureSource.Open()
            Dim fileName As String = System.IO.Path.GetFileNameWithoutExtension(Me.ShapePathFileName)
            Dim dataTable As DataTable = FeatureSource.ExecuteQuery(String.Format(“select ID_0, {0} from {1}”, linkFieldName, fileName))
 
            For Each dataRow As DataRow In dataTable.Rows
                idLinkFieldDictionary.Add(dataRow(“ID_0”).ToString(), dataRow(linkFieldName).ToString())
            Next
            For Each customColumnName As String In customColumnNames
                Dim dictionary As New Dictionary(Of String, String)()
                ’ Here is you own code getting the dictionary from the LinkField To The customColumn you want
                ’ This sample is using DataTable as the external database. You can change it to consume your own databases.
                For Each dataRow As DataRow In externalDataBase.Rows
                    dictionary.Add(dataRow(linkFieldName).ToString(), dataRow(customColumnName).ToString())
                Next
                customFieldsDictionaries.Add(customColumnName, dictionary)
            Next
        End Sub
 
        Private Sub FeatureSource_CustomColumnFetch(sender As Object, e As CustomColumnFetchEventArgs)
            Dim LinkFieldValue As String = idLinkFieldDictionary(e.Id)
            If customFieldsDictionaries(e.ColumnName).ContainsKey(LinkFieldValue) Then
                e.ColumnValue = customFieldsDictionaries(e.ColumnName)(LinkFieldValue)
            End If
        End Sub
    End Class

I will give a try what you have suggested and will let you know.



Thanks,

Naeem

Hello Troy,



I have tried the code which you mentioned in your post, I have colour_map field column not in FeatureSource, it is in CustomFieldsDictionaries for that I shared the class "CustomDataShapeFileFeatureLayer" with you. this colour_map field I am formulating based on Number of Projects in a specfic area. If I am doing it wrongly, please do let me know what is the correct way as this problem has taken a lot of time and I need to finish this and then to go for purchase of the licenses etc.



With Best Regards,

Naeem

One more thing to add, colour_map field is basically hookup data, this is not part of shape file.

Hi Naeem,



I see, so I guess that is the problem that colour_map column is not part of shape file. In order to use Value Style, we have to make sure your layer has this colour_map column. 

Here I think has two solutions for it: One is adding a new column named "colour_map" for the shape file at first, the other one is using an InmemoryFeatureLayer instead of the CustomDataShapeFileFeatureLayer, then in this InMemoryFeatureLayer, add the "colour_map" column and fill featuresource. Some codes as following:


Dim layer As New InMemoryFeatureLayer(New FeatureSourceColumn() {New FeatureSourceColumn("colour_map")}, New Feature() {})
layer.Open()
 
Dim newFeature As New Feature()
newFeature.ColumnValues.Add("colour_map", "1")
 
layer.FeatureSource.BeginTransaction()
layer.FeatureSource.AddFeature(newFeature)
layer.FeatureSource.CommitTransaction()
 
layer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = valueStyle

Please let us know if any questions.

Thanks,

Troy

Dear Troy,



Thanks for your reply. But that did not help me at all. I have been trying your solutions for last two days but all in vain. 



In response to "In order to use Value Style, we have to make sure your layer has this colour_map column.", My shape file is not containing column named "colour_map", and I am able to apply ValueStyle by using that column.



With CustomdataShapeLayer, we are getting the shapes coloured when I debug it shows the correct values in Dictionaries but when we apply value style on that then it is colouring the shapes differently. 



First of all, Please let me know do you understand my problem? Am I clear in my questions? Because it has been almost 10 days and I am struggling to solve this issue. 



Thanks and Regards,

Naeem

Naeem, 



I happened to see this thread and just chime in. 



Seems you have a value style based on “colour_map” column which doesn’t exist in your shape file. This can be accomplished by using CustomColumnFetch event.  Here attached is a sample for you, where I use the event to arbitrarily divide the features into 3 groups(by setting different value to “colour_map” column) and use ValueStyle to render them accordingly. Like your case, “colour_map” doesn’t exist in the shape file, it is dynamically set in the event. So the trick is to label the “colour_map” column on the feature and you can easily figure out the reason if it is not rendered as expected. 







Ben

ValueStylesTest.zip (95 KB)

Dear Ben,



Thanks for your email. Yes, you are right I am doing in the same way as you have described and I have that CustomColumnFetch event as well and it is called when I am debugging it. Only issue is it is coloring differently. Like in One Province Punjab I have number of projects 5, according to value style it should color it Red, but it is coloring it yellow and other province is KPK which has 10 projects, it should color it Yellow and it is coloring it Red. This is where I am stuck. Through debugging, I have checked the data is loaded correctly but the color is not assigned as I did in Value Style.



I hope you will further see it, If you are interested I can upload the code as well.



Thanks a lot for your kind response and understanding the issue,



Regards,

Naeem 

Thanks Ben, I think I may have some misunderstandings on the CustomColumnFetch event as I though it is impossible with this event before. 



Naeem, sorry for the fault on CustomColumnFetch, but I do understand you issue as you explained it clear. Currently, all your codes looks fine except I am a few confused on the test data you supplied before, for example,



Area= "Punjab"
AreaID=6
Total:1


As I understand, the Total should be the projects count, but you mentioned the province Punjab is 5. 



Also, I tried to download your shape files from unocha.org/pakistan/maps-graphics/administrative-maps, but unlucky to find them. Would you please: 


        
  • Send your shape files to us via  forumsupport@thinkgeo.com, if the data is large, please contact support@thinkgeo.com, they will setup a ftp for you.

  •     
  • Send the related classes files.

  •     
  • Including some hard-codes test data as I guess some data like projects number may be from other datasources in your local.


Thanks,



Troy

Thanks Troy,



I have sent you the code and shape files including some dummy data in excel for your review. Please have a look and let me know where do I mistake.



Regards,

Naeem