ThinkGeo.com    |     Documentation    |     Premium Support

Put Image or even control on the map

 I  have questions. I start to learn Map Suite Desktop Edition. I am running yours examples. I can not find out the simple way to  put the common windows control on the map like Image (made in the memory). Is it  simply way to put the icon (bitmap) from memory stream on the map? I find out  only streaming form Tiff images, but I am new with using your solution. I am trying to make some graphics like:


 


 Bitmap obraz = new System.Drawing.Bitmap(30, 30);


            using (Graphics g = Graphics.FromImage(obraz))


            {


                Brush brSolid = new SolidBrush(Color.Blue);


                g.FillPie(brSolid, 0, 0, 30, 30, 28, 15);               


            } 


 


and then put it on the map in point given by coordinates (this is simple FillPie as example but my picture is more complicated - so using your multiline or similar graphics  can not replace it).


How to do it without using files ?


 


Best regards


Piotr



 Hi, I've done some progress:



 var pointLayer = new InMemoryFeatureLayer();
            pointLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.PointType =  PointType.Bitmap;            
            pointLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.Image = new GeoImage(MakeTiff(20,Color.Red,Color.Green,Color.Yellow));
            pointLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
  

//making tiff stream:


    private MemoryStream MakeTiff(int i, Color red, Color green, Color yellow)
        {
           
            var obraz = new Bitmap(i+5, i+5);
           

            using (var g = Graphics.FromImage(obraz))
            {
                g.SmoothingMode =
        System.Drawing.Drawing2D.SmoothingMode.AntiAlias;


                var abrSolid = new SolidBrush(red);
                g.FillPie(abrSolid, 0, 0, i, i, 0, 119);
                var bbrSolid = new SolidBrush(green);
                g.FillPie(bbrSolid, 0, 0, i, i, 120, 119);
                var cbrSolid = new SolidBrush(yellow);
                g.FillPie(cbrSolid, 0, 0, i, i, 240, 119);
            }
            var memo = new MemoryStream();
            obraz.Save(memo, ImageFormat.Tiff);
            return memo;
        }



// I can put it on the image:

 var feature = new Feature(18.580542, 54.272241, "BSR1");

                var pointLayer = (InMemoryFeatureLayer) winformsMap1.FindFeatureLayer("PointLayer");
                if (!pointLayer.InternalFeatures.Contains("BSR1"))
                {
                    pointLayer.InternalFeatures.Add("BSR1", feature);                     
                }


//but I can not modify it

 InMemoryFeatureLayer inMemoryLayer = (InMemoryFeatureLayer)winformsMap1.FindFeatureLayer("PointLayer");

            inMemoryLayer.Open();
            inMemoryLayer.EditTools.BeginTransaction();
            inMemoryLayer.EditTools.Update(new Feature(???????????????????????, "BSR1"));
            inMemoryLayer.EditTools.CommitTransaction();
            inMemoryLayer.Close();


            winformsMap1.Refresh(winformsMap1.Overlays["PointOverlay"]);

How to change / modify the bitmap?



Piotr,


Thanks for your interests in Map Suite components.
I am not sure about your exact requirement, while it is a good solution to shown those point features on the map with bitmap. When you want to change the bitmaps positions, then just do as you have done to update the feature shape. While when you want to change the bitmap itself, you probably need to change the Image of the style.

pointLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.Image = newImage;

Any more questions please feel free to let me know.
Thanks.
Yale

 Thanks for your time, I will drop some more light on it.





I have to write program to visualize on the map the state of the GSM base stations. About 11 000 base stations. Each  one have 2-6 sectors (directions antenna). We count the number of failed connections for each sector in constant period of time. This data go on-line to program by network.



Base station can be with sectors working in different directions and number of sectors is 2 to 6. The state is visualized by changing the color of the pie.
 
So this kind of object I can easy build by tools in C# as bitmap and put it on the map if there is no worry about using 3 000 of layers (there is low number of base station with the same sectors direction and numbers, so we can find out similar and go down from 11 000 to 3 000).
 
And then when data income on-line we have to change colors to show of sectors state in the bitmap - mean change the bitmap for another one.
 
It will be like in your example with a plane starting form US and landing in UE - the position of the plane's body is rather strange  when it starting. We will able to change the plane's body position by modify the bitmap. 
 
Best regards
Piotr
 

Piotr,


Thanks for your post and feedback.
 
I want to clarify 2 things which you may already have known.
1)      In our HowDoI sample sample, it is very similar with the code provided from you. Here when setting PointStyle we use the image file existing in the installer path “Prop Plane.png”.
 

bitmapLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.Image = new GeoImage(@"..\..\SampleData\Images\Prop Plane.png");

 
So, as I suggest above, just change the image to what you want.
 
2)If you have hundreds of thousands of images to be shown on the Map control, and the image is determined by some value of the feature, please consider to use the ValueStyle or IconValueStyle.
 
It would be nice if a sample code to show the problem, it definitely make things easier to understand to get it fixed.
 
Any more questions please feel free to let me know.
 
Thanks.
 
Yale

 The problem is that I can not give the code sample - I have no idea how to do it in your SDK, but I do try give better clarify.


Good example will be a flower - how to show the flower with all petal in various colors changing every 30 seconds. Moreover - you have thousand of flowers and it is important to have every petal in various angle and direction but all flowers have the same size.


Your example show how to generate the bitmap and then put it as many times as you wish on the map.


In this case I have to generate all bitmaps/symbols on the start and attach them to new layer of the map.


It means:


flower can have various number of petals (1,2,3,4,5,6)


flower can have various colors of petals but you have to generate all possible color variation!


flower can have various orientation and angle size of petals


- so only good solution in this case is to dynamically changing the already paced bitmap on the map programmatic. 


 


On the Code Community I found interesting part of code - dynamically changing of the text labels



 var labelLayer = new InMemoryFeatureLayer();
            labelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateMaskTextStyle("Label", new GeoFont("Arial", 10),
                 new GeoSolidBrush(GeoColor.SimpleColors.Black), new AreaStyle(new GeoPen(GeoColor.StandardColors.Black), new GeoSolidBrush(GeoColor.StandardColors.LightGoldenrodYellow)), 10, 0);
            labelLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.SimpleColors.Yellow, 1);
            labelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            labelLayer.Open();
            labelLayer.Columns.Add(new FeatureSourceColumn("Label"));
            labelLayer.Close();

[....]
//and in dynamic part of code

 pointLayer = (InMemoryFeatureLayer)winformsMap1.FindFeatureLayer("iconLayer");
                if (!pointLayer.InternalFeatures.Contains(Name))
                {
                    PointShape pointShape1 = new PointShape(d, d1);
                    Feature newFeature1 = new Feature(pointShape1);
                    newFeature1.ColumnValues.Add("Label", Name);
                    pointLayer.InternalFeatures.Add(Name, newFeature1);

                }


 


 


One Code Forum


 


Would you like to put the analogical  part of code with example with IconValueStyle?


Best regards


Piotr


 


 



Piotr,


Thanks for your input and post, hope following code snippet helps. In this IconValueStyle, we will use a.png if the value is 1 and use b.png if the value is 2 etc, on top of the png , we can also add some label “PeterNumber”.

 

IconValueStyle iconValueStyle = new IconValueStyle("PetalNumber");
IconValueItem item1 = new IconValueItem("1", "\\bitmaps\\a.png", TextStyles.City1("PetalNumber"));
IconValueItem item2 = new IconValueItem("2", "\\bitmaps\\b.png", TextStyles.City1("PetalNumber"));
IconValueItem item3 = new IconValueItem("3", "\\bitmaps\\c.png", TextStyles.City1("PetalNumber"));
IconValueItem item4 = new IconValueItem("4", "\\bitmaps\\d.png", TextStyles.City1("PetalNumber"));
iconValueStyle.IconValueItems.Add(item1);
iconValueStyle.IconValueItems.Add(item2);
iconValueStyle.IconValueItems.Add(item3);
iconValueStyle.IconValueItems.Add(item4);


Any more questions please feel free to let me know.
Thanks.
Yale

Thanks a lot


There is a note in API doc, like follow:


When you create an IconValueStyle, you need to add multiple IconValueItems to its collection


 


So please for example with changing the icon on the map into new icon not know before layer init - is it possible like in character label it was?


I was try like that:



 var iconLayer = new InMemoryFeatureLayer();           
            iconLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            
            MyIconValueStyle = new IconValueStyle("PetalNumber"); 
            IconValueItem item1 = new IconValueItem("BSR1", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\1.png", TextStyles.City1("PetalNumber"));
            IconValueItem item2 = new IconValueItem("BSR2", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\2.png", TextStyles.City1("PetalNumber"));
            IconValueItem item3 = new IconValueItem("BSR3", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\3.png", TextStyles.City1("PetalNumber"));
            IconValueItem item4 = new IconValueItem("BSR4", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\4.png", TextStyles.City1("PetalNumber")); 
            MyIconValueStyle.IconValueItems.Add(item1); 
            MyIconValueStyle.IconValueItems.Add(item2); 
            MyIconValueStyle.IconValueItems.Add(item3); 
            MyIconValueStyle.IconValueItems.Add(item4);
            iconLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(MyIconValueStyle);            
            iconLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            iconLayer.Open();
            iconLayer.Columns.Add(new FeatureSourceColumn("PetalNumber"));
            iconLayer.Close();


//and after showing the map I try to change icon for icon taken after init

pointLayer = (InMemoryFeatureLayer)winformsMap1.FindFeatureLayer("iconLayer");
                if (pointLayer != null && !pointLayer.InternalFeatures.Contains(Name))
                {
                    PointShape pointShape1 = new PointShape(d, d1);
                    Feature newFeature1 = new Feature(pointShape1);

                    
                    IconValueItem changer = new IconValueItem("BSR1", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\4.png", TextStyles.City1("PetalNumber"));
                    if (MyIconValueStyle.IconValueItems.Contains(changer))
                        MyIconValueStyle.IconValueItems.Remove(changer);

                    MyIconValueStyle.IconValueItems.Add(changer); 
                    
                    newFeature1.ColumnValues.Add("PetalNumber", Name);
                    pointLayer.InternalFeatures.Add(Name, newFeature1);

                }

But it does not working - the icon with key BSR1 stay the same. When you do it with text - the text can be new object but when you take icon - it can be only know key value - the icon object has to be created before showing the map - is it true? Is there any way to manage the collection on-line? Maybe I have to remove and add it to the layer again?


 


 


Maybe I should change approach and generate the tiff image in all and put it on the map, but how to tie the location of the points on the map with tiff picture?


Or add as many layers as base stations or better from refreshing point of view add as many Overlays as base stations (11 000) - possible?



 



Piotr,


Thanks for your post and feedback.
Following code snippet shows you two ways to change the path dynamically.

 

IconValueStyle iconValueStyle = new IconValueStyle("PetalNumber");
IconValueItem item1 = new IconValueItem("1", "\\bitmaps\\a.png", TextStyles.City1("PetalNumber"));
IconValueItem item2 = new IconValueItem("2", "\\bitmaps\\b.png", TextStyles.City1("PetalNumber"));
IconValueItem item3 = new IconValueItem("3", "\\bitmaps\\c.png", TextStyles.City1("PetalNumber"));
IconValueItem item4 = new IconValueItem("4", "\\bitmaps\\d.png", TextStyles.City1("PetalNumber"));
iconValueStyle.IconValueItems.Add(item1);
iconValueStyle.IconValueItems.Add(item2);
iconValueStyle.IconValueItems.Add(item3);
iconValueStyle.IconValueItems.Add(item4);
 
//Solution1:
item4.IconFilePathName = "\\bitmaps\\e.png";
 
//Solution2:
iconValueStyle.IconValueItems[3].IconFilePathName = "\\bitmaps\\e.png";


Any more questions please feel free to let me know.
Thanks.
Yale

Dear Yale, I think that simple knowledge of operation on collection is well known to me, the question was about changing the icon AFTER winformsMap1.Refresh();
Now I start to use plenty of overlays – but the performance is weak.
 
All about my questions are:
 
How to change bitmap/icon on the visible map on the same size bitmap/icon with diffent contents without adding new layer or overlay?
 
ofter some time I notice that it possible like that:
 

pointLayer = (InMemoryFeatureLayer)winformsMap1.FindFeatureLayer("iconLayer");
                if (pointLayer != null && !pointLayer.InternalFeatures.Contains(Name))
                {
                    PointShape pointShape1 = new PointShape(d, d1);
                    Feature newFeature1 = new Feature(pointShape1);


                    IconValueItem changer = new IconValueItem("BSR2", new GeoImage(MakeTiff2(20, Color.Red, Rumb.E)), TextStyles.City1("PetalNumber"));
                    IconValueStyle style = new IconValueStyle("PetalNumber");
                    if (pointLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Count > 0)
                        ((IconValueStyle) (pointLayer.ZoomLevelSet.ZoomLevel01.CustomStyles[0])).IconValueItems[1] =
                            changer;
                    
                    
                            newFeature1.ColumnValues.Add("PetalNumber", Name);
                    pointLayer.InternalFeatures.Add(Name, newFeature1);

//MakeTiff2 just make stream of tiff as new icon - the Image form Windows is not the same like Image form ThinkGeo so I stay with tiff streaming

 

But the point where I call CustomStyles is weak - there should be possible to get it by key.


 
 
The next problem with Icon:
 


//var item1 = new IconValueItem("TEST", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\1.png", TextStyles.NoData1("SectorNumber"));
            var item1 = new IconValueItem("TEST", @"C:\Users\user\Documents\Visual Studio 2008\Projects\ikony\1.png",  TextStyles.CreateMaskTextStyle("SectorNumber", new GeoFont("Arial", 10), new GeoSolidBrush(GeoColor.SimpleColors.Black), new AreaStyle(new GeoPen(GeoColor.StandardColors.Black), new GeoSolidBrush(GeoColor.StandardColors.LightGoldenrodYellow)), 10, 0));

Changing the TextStyles cause fatal error when zoom the map, generally how to remove the fonts at all?

 



Piotr,


Sorry for the delay.
I want to clarify the requirement and then probably I can try to make a sample for it.
Let us say we have 5 feature with one column, their corresponding value for this column is different:
Feature 1 columnValue is “A”
Feature 2 columnValue is “B”
Feature 3 columnValue is “D”
Feature 4 columnValue is “A”
Feature 5 columnValue is “C”
We want to use IconValueStyle for these features, let us say:
“A” : a.png
“B” : b.png
“C” : c.png
“D” : d.png
Then after loading these features, I want to replace a.png into a new same size png file “aa.png” dynamically by clicking on one button or some event.
Please do not hesitate to correct me if my above description is making any mistakes or cannot satisfy the requirement.
Any more questions please feel free to let me know.
Thanks.
Yale

 Yale, there are some important notice - the "aa.png" is not known before so we can not add it to the collection form start,


and now I come to the point where it is working 



public void Show()
       {
           BtsDir.MyIconValueStyle.IconValueItems.Remove(MyIconValueItem);
           MyIconValueItem = new IconValueItem(Config.Name, new GeoImage(MakeTiff(20)), TextStyles.City1("SectorNumber"));
           BtsDir.MyIconValueStyle.IconValueItems.Add(MyIconValueItem);
       }

The problem I notice that I can not only change the object MyIconValueItem - I have to remove and add it to the IconValueStyle.IconValueItem collection. The main problem now is that when I was basing on bitmaps and N-number of overlays, the bitmap has been centered on right position and now when I've started do it by IconValueStyle I can not get rid of the Text label centered over the icon - and the center of the icon not cover the position. How to fix it?



Piotr, 
  
 Thanks for your post and questions. 
  
 In my understanding, the TextStyle is attached with the IconValueItem, so it should go away if we remove the IconValueItem.  Could you send the sample you mentioned to me to recreate this problem? 
  
 Any more questions please feel free to let me know. 
  
 Thanks. 
  
 Yang 



 


 Yang, thanks for answers - as I wrote before,  in first approach  I’ve used the bitmaps and 8000 overlays and the performance was poor but visual effects good (the picture frame - A with the fragment of the peninsula with the feature located exactly in the position and name on the yellow background on the right).


 
In the second approach I’ve used the IconValue – the performance is good but but visual effects not acceptable, please look at the picture - frame B with the same fragment of the peninsula with the same feature – icon is not center over the position and the text goes thru the icon. 
 
The question is how to have a graphics effect like picture – frame B using the IconValues. I was try to have only icon without the text with no results. How to center icon over position?
 
Best regards
Piotr
 

Piotr,


Thanks for your post and feedback.
I am sorry to misunderstand your points in previous posts. I think we can fix this issue with following 2 solutions.
Solution1:Try to change the PointPlacement of the IconValueStyle.


iconValueStyle.PointPlacement = PointPlacement.Center;

 
Solution2: Try to set the Offset for the text style attached to the IconValueItem.


TextStyle textStyle = TextStyles.City1("Name");
textStyle.XOffsetInPixel = 30;
textStyle.YOffsetInPixel = 40;

IconValueItem iconValueItem = new IconValueItem("A", bitmapImage, textStyle);

 
Any more questions or unclear please feel free to let me know.
Thanks.
Yale

 Yale, the solution no 1 works fine - thanks. The solution no 2 not working at all - the text is moved but the icon also. If it will be possible to make just text invisible I can add the text in next layer.


Best regards


Piotr



Piotr,


Thanks for your post and feedback.
Yes, the solution 2 will move the Icon and text at the same time as you address, thanks for pointing this out and let us know your status.
Any more questions please feel free to let me know.
Thanks.
Yang

Thanks Yang, and what about making icons alone - I mean without any text visible? 
  
 Best regards 
 Piotr

Piotr, 
  
 Thanks for your post and feedback. Why not using the ValueStyle instead of IoncValueStyle to just keep Icon? Just take a try and let me know if any problems. 
  
 Thanks. 
  
 Yale 


 Yale, good point - ValueStyle makes this job fine, I take sample form:


gis.thinkgeo.com/Support/Dis...fault.aspx


and implement into my code - all done.


Thank you for your time!


Piotr