ThinkGeo.com    |     Documentation    |     Premium Support

Drawing lines in CustomOverlays

im puzzled on the new release (3.0.131). When using CustomOverlays, how do i draw a line between 2 points? i understand from the samples, to draw a line in Static or Dynamic Overlays is:


InMemoryFeatureLayer shapeLayer = (InMemoryFeatureLayer)Map1.DynamicOverlay.Layers["ShapeLayer"];   

MultilineShape line = p1.GetShortestLineTo(p2, GeographyUnit.DecimalDegree);

shapeLayer.InternalFeatures.Add("Distance", new Feature(line));


But in CustomOverlays, you can't do like this:


InMemoryFeatureLayer shapeLayer = (InMemoryFeatureLayer)Map1.CustomOverlays["ShapeOverlay"];  ---> ERROR


So how can i do it?


 


 



Ric,


Overlay and Layer are different. Actually the LayerOverlay contains Layers. For your case, you need to create a LayerOverlay with your layers and then add it to the CustomOverlays collection. To find a layer in the CustomOverlays, you need first find the overlay that contains the layer and then find the layer in it. Below is the code:




InMemoryFeatureLayer shapeLayer = (InMemoryFeatureLayer)((LayerOverlay)Map1.CustomOverlays["ShapeOverlay"]).Layers["ShapeLayer"];

Here is a post about Overlays, please have a look if you are interested.


 


gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/12/aft/4876/afv/topic/Default.aspx 


Ben



Thanks Ben. i tried this to draw 2 points and a line between them in CustomOverlay, but the 2 points won’t come out unless i move the map: 
  
 markerOverlay.Features.Add(“P1”, new Feature(p1)); 
 markerOverlay.Features.Add(“P2”, new Feature(p2)); 
 … 
 InMemoryFeatureLayer shapeLayer = (InMemoryFeatureLayer)((LayerOverlay)Map1.CustomOverlays[“ShapeOverlay”]).Layers[“ShapeLayer”]; 
 MultilineShape line = p1.GetShortestLineTo(p2, GeographyUnit.DecimalDegree); 
 shapeLayer.InternalFeatures.Add(“Distance”, new Feature(line)); 
  
 1) Obviously, i need to call shapeLayer.Draw(), but it has some parameters (GeoCanvas…) that i dont know how to set them, unlike in DynamicOverlay, it is straightforward. Can you tell me how? 
 2) i dont see the line between them, something i do wrong? 
  
 Ric 
  


LayerOverlay has a method redraw() can you try that? 
  
 ((LayerOverlay)Map1.CustomOverlays["ShapeOverlay"]).Redraw() 


The 2 points were displayed without the need of "dragging" the map, but the line is still not displayed, even if i move the map. Here is my code:

 




InMemoryFeatureLayer shapeLayer = new InMemoryFeatureLayer();
        shapeLayer.Name = "LinesShapeLayer";
        ...

        InMemoryMarkerOverlay markerOverlay = new InMemoryMarkerOverlay("Markers");
        markerOverlay.ZoomLevelSet.ZoomLevel01.DefaultMarkerStyle.WebImage = new WebImage("images/blue.gif", 30, 30);
        ...

        LayerOverlay shapeOverlay = new LayerOverlay("ShapeOverlay");
        shapeOverlay.Layers.Add(shapeLayer);

        Map1.CustomOverlays.Add(markerOverlay);
        Map1.CustomOverlays.Add(shapeOverlay);


when a TestDeviceFilter button is clicked:
 


 InMemoryMarkerOverlay markerOverlay = (InMemoryMarkerOverlay)Map1.CustomOverlays["Markers"];
        PointShape p1 = new PointShape(xxx,xxx);
        PointShape p2 = new PointShape(xxx+0.001, xxx+0.001);

        markerOverlay.Features.Add("P1", new Feature(p1));
        markerOverlay.Features.Add("P2", new Feature(p2));

        MultilineShape line = p1.GetShortestLineTo(p2, GeographyUnit.DecimalDegree);
        ((LayerOverlay)Map1.CustomOverlays["ShapeOverlay"]).Redraw();





 


In this CustomOverlay mode, calling a LayerOverlay.Redraw() will cause the map to flicker?


 



Post corrected



Ric, 
  
 It seems that you didn’t add the line feature to the map in the button click event. I have changed the code a bit and please have a look. 
  
 
// when a TestDeviceFilter button is clicked:

InMemoryMarkerOverlay markerOverlay = (InMemoryMarkerOverlay)Map1.CustomOverlays["Markers"];
            PointShape p1 = new PointShape(xxx, xxx);
            PointShape p2 = new PointShape(xxx + 0.001, xxx + 0.001);

            markerOverlay.Features.Add("P1", new Feature(p1));
            markerOverlay.Features.Add("P2", new Feature(p2));

            InMemoryFeatureLayer shapeLayer = (InMemoryFeatureLayer)((LayerOverlay)Map1.CustomOverlays["ShapeOverlay"]).Layers["ShapeLayer"];
            MultilineShape line = p1.GetShortestLineTo(p2, GeographyUnit.DecimalDegree);
            shapeLayer.InternalFeatures.Add("Distance", new Feature(line));
            ((LayerOverlay)Map1.CustomOverlays["ShapeOverlay"]).Redraw();

 
 Ben. 


Ben, i followed your code, but still the 2 points were drawn, the line between them is not drawn. Maybe i did something wrong in the declaration of layers and overlays. Here are they:



InMemoryFeatureLayer shapeLayer = new InMemoryFeatureLayer();
//...etc
InMemoryMarkerOverlay markerOverlay = new InMemoryMarkerOverlay("Markers");
//...etc
LayerOverlay shapeOverlay = new LayerOverlay("ShapeOverlay");
shapeOverlay.Layers.Add("ShapeLayer", shapeLayer);

Map1.CustomOverlays.Add(markerOverlay);
Map1.CustomOverlays.Add(shapeOverlay);

 


 



Ric,


Maybe something goes wrong in your "//..etc", :) here is the sample code and please have a look.


Ben



260-Post5043.zip (7.07 KB)

Ben,


 


Yes your attached code runs fine, the 2 markers and the line were drawn. However, when i add the base map BEFORE InMemoryFeatureLayer and InMemoryMarkerOverlay, the maps and markers were drawn, but the line isn't. i don't know if i have to do something different on this new 3.0.131 version, or something wrong with my code. Here it is:



ShapeFileFeatureLayer ExpresswayLayer = new ShapeFileFeatureLayer(@"C:\Maps\Roads_polyline.shp");
ExpresswayLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.LocalRoad1;
ExpresswayLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
ExpresswayLayer.RequireIndex = true;

ShapeFileFeatureLayer ExpresswayLabelLayer = new ShapeFileFeatureLayer(@"C:\Maps\Roads_Cities_polyline.shp");
ExpresswayLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.LocalRoad1("STNAME");
ExpresswayLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
ExpresswayLabelLayer.RequireIndex = true;
ExpresswayLabelLayer.DrawingMarginPercentage = 100;

LayerOverlay myBaseOverlay = new LayerOverlay("MyBaseOverlay");
myBaseOverlay.TileType = TileType.MultipleTile;
myBaseOverlay.IsBaseOverlay = true;
myBaseOverlay.Layers.Add(ExpresswayLayer);
myBaseOverlay.Layers.Add(ExpresswayLabelLayer);

Map1.CustomOverlays.Add(myBaseOverlay);


Ric, 


ShapeOverlay and MarkerOverlay should all be non-base overlay. MarkerOverlay by default is non-base while ShapeOverlay by default is not, that's why when adding another BaseOverlay at the bottom, you can only see the markers but not the line. To solve this problem, you can simply add the following one line to make the ShapeOverlay non base.
         
                     LayerOverlay shapeOverlay = new LayerOverlay("ShapeOverlay");
                     shapeOverlay.IsBaseOverlay = false;
                     shapeOverlay.Layers.Add("ShapeLayer", shapeLayer);
 
The Overlay has the similar concept as the layer. Different types of overlays stack over each other to form a map. There are basically two kinds of overlay: base overlay and non-base overlay.
 
The base overlay has the IsBaseOverlay property set to true. It is displayed as the background image of the map. In an OverlaySwither, they are listed with radio buttons beside their names. There is only one base overlay displayed at a time. You can click the radio button to switch between the base overlays.
 
The non-base overlay has the IsBaseOverlay property set to false. Non-base overlays can overlap other overlays and display at the same time. In an OverlaySwither, they are listed with check boxes beside their names. You can click the check box to show or hide it.
 
Hope that makes sense, let me know for any queries.
 
The last and the most important: Merry Christmas and Happy New Year!  :)
 
Ben

Ben, 



Thank you so much, this particular issue is solved, you have explained it well in details. Also, you were working on Holiday season!


Merry Christmas too, and happy New Year!



Thanks Ric, Your words let me feel all the work is deserved. I will keep trying my best to provide the best service in the new year!

Hi , 





When I try to add more no of lines ( around 12000) using customOverlay with InMemoryFeatureLayer, I am getting the script error as I was getting the error while trying to add more markers using SimpleMarkerOverlay. 


Is there any workaround to solve this issue. 


Thanks


Raja


 



Raja, 
 The InMemoryFeatureLayer are used in the Marker/Popup httphandler, right? I think that will not give you that script error. The issue is caused that you added 12000 marker on the server side, That’s a huge number, we can image that the marker DOM tree need long time to create, so the error happened. Besides using httphanlder to get popup information on the fly, we also need to create another MarkerManager to filter the markers based on the ZoomLevel and make sure the Brower gets an acceptable number of markers, right?    
 I think the MarkerManager can filter the markers based on the screen distance between each other based on zoom levels. For instance, we can define there should be no other markers around it in 10 pixel distance. 
 Thanks, 
 Johnny

Raja, 
  
 You means the Maker issue or something else? Please detail it. 
  
 Thanks, 
 Johnny

Dear Johnny,


Thank you for your reply. I am very much grateful to you.


I created the markers using InMemoryMakerOverlay. And the popup also no issue. So there is no issue in the markers level.


I want to create lines assuming the parent -child relations. So I created lines using InMemoryFeatureLayer. That is giving the issue.


The script error is comming when I create more lines while zooming.


Thanks.


Raja.


 


 



Raja, 
  
 Can you post the script error and detail where you create the InMemoryFeatureLayer? 
  
 Johnny

Dear Johnny,


Please find the error as below.




A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete.



Script: localhost/map/opl_GeoResource.axd:43


The way I created the lines :


CreateLine Layer as below :


private void CreateLineLayer()


{

            InMemoryFeatureLayer LineLayer

                        = new InMemoryFeatureLayer();

           LineLayer.Name = _LineLayerName;

            LineLayer.ZoomLevelSet.ZoomLevel01.

                DefaultPointStyle = PointStyles.City7;

            LineLayer.ZoomLevelSet.ZoomLevel01.

                DefaultLineStyle = LineStyles.CreateSimpleLineStyle(

                GeoColor.SimpleColors.Green,

                PrimaryLineWidth, true);

            LineLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel

                = ApplyUntilZoomLevel.Level20;


   LayerOverlay OverLayLine = new LayerOverlay();

            OverLayLine .Name = _MapLineOverlayName;

            OverLayLine .Layers.Add(_LineLayerName,

                            activeMapLineLayer);

            mapControl.CustomOverlays.Add(OverLayLine );


}


 


private void  CreateLines(){


           mapLineLayer =

                    (InMemoryFeatureLayer)((LayerOverlay)

                    (mapControl.CustomOverlays[2])).

                    Layers[_LineLayerName];

 


             foreach (DataRow linerow in LineMarkers)

             {


             // Lines


                                  Collection<Vertex> points =

                                        new Collection<Vertex>();

                                    double pointX =

                                            Convert.ToDouble(linerow["StartLongitude"]);

                                    double pointY =

                                            Convert.ToDouble(linerow["StartLatitude"]);

                                    points.Add(new Vertex(pointX, pointY));

                                    pointX = Convert.ToDouble(linerow["EndLongitude"]);

                                    pointY = Convert.ToDouble(linerow["EndLongitude"]);

                                    points.Add(new Vertex(pointX, pointY));



                                    LineShape line = new LineShape(points);


 


                                        string lineId = string.Format(

                                        "{0}{1}",

                                        _LineLayer,

                                        linerow["markerId"]);



                                    // Adding the line with layer

                                    mapLineLayer .InternalFeatures.Add(

                                        lineId,

                                        new ThinkGeo.MapSuite.Core.Feature(line));

                                    mapLayer.DrawingQuality =

                                        DrawingQuality.Default;  


         }


}


Thanks


Raja


 



 


Raja,
I’m unable to recreate what you descripted. I load all the main road data that have 989786 line shapes, but still run fine except a long loading time. Here are the code I used for test, please try:



public partial class DisplayASimpleMap : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"));
                Map1.CurrentExtent = new RectangleShape(-125, 72, 50, -46);
                Map1.MapUnit = GeographyUnit.DecimalDegree;

                WorldMapKitWmsWebOverlay worldMapKitOverlay = new WorldMapKitWmsWebOverlay();
                Map1.CustomOverlays.Add(worldMapKitOverlay);


                InMemoryFeatureLayer LineLayer = new InMemoryFeatureLayer();
                LineLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.City7;
                LineLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.SimpleColors.Green, 2, true);
                LineLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

                LayerOverlay OverLayLine = new LayerOverlay();
                OverLayLine.Layers.Add("LineLayer", LineLayer);
                OverLayLine.IsBaseOverlay = false;
                Map1.CustomOverlays.Add(OverLayLine);

                // In the shape file, it has 989786  lineshapes.
                ShapeFileFeatureSource featureSoruce = new ShapeFileFeatureSource(@"C:\21-40\OK\OKlkaA40.shp");
                featureSoruce.Open();
                Collection<Feature> features = featureSoruce.GetAllFeatures(ReturningColumnsType.NoColumns);
                foreach (Feature feature in features)
                {
                    LineShape line = GetLine((LineBaseShape)feature.GetShape());
                    LineLayer.InternalFeatures.Add(line.Id, new ThinkGeo.MapSuite.Core.Feature(line));
                }
            }
        }

        private LineShape GetLine(LineBaseShape lineBaseShape)
        {
            if (lineBaseShape.GetType() == typeof(MultilineShape))
            {
                return ((MultilineShape)lineBaseShape).Lines[0];
            }
            else
            {
                return (LineShape)lineBaseShape;
            }
        }

    }



 
Thanks,
Johnny