ThinkGeo.com    |     Documentation    |     Premium Support

Priint map on server side adding scalebar on pdf

Hi

i am working in mvc and and printing map to pdf
Issue i am facing is i am trying to add scale bar on my pdf after printing …
It adds ShapeOverlay, WorldMap and LayersOverLay correctly
But when i try to add adornment layer and and marker over it gives me error
“The given key was not present in the dictionary.”
how can we loop through in memorymarkeroverlay to make them visible when it goes for printing
Here is the print function

 public string MapPrint(Map map, GeoCollection<object> args) 
  {

        PdfGeoCanvas pdfGeoCanvas = new PdfGeoCanvas();

        PdfDocument document = new PdfDocument();            

        PdfPage page = document.AddPage();

        page.Orientation = PageOrientation.Portrait;

        page.Size = PageSize.A4;

        string font = "Roboto";

        string Area = "";

        List<LayerOverlay> lstlayeroverlay = new List<LayerOverlay>();

        List<InMemoryMarkerOverlay> lstmarkeroverlay
= new List<InMemoryMarkerOverlay>();

        //AdornmentOverlay adornmentoverlay = new
  AdornmentOverlay();

        List<LegendResult> lstlegend = new List<LegendResult>();

        lstlayeroverlay.Add((LayerOverlay)map.CustomOverlays["WorldMap"]);            

        lstlayeroverlay.Add((LayerOverlay)map.CustomOverlays["LayersOverlay"]);

        lstlayeroverlay.Add((LayerOverlay)map.CustomOverlays["ShapeOverlay"]);

        //
 lstlayeroverlay.Add((LayerOverlay)map.CustomOverlays["ScaleBar"]);

  lstmarkeroverlay.Add((InMemoryMarkerOverlay)map.CustomOverlays["GirlsMarkerOverlay"]);
 lstmarkeroverlay.Add((InMemoryMarkerOverlay)map.CustomOverlays["BoysMarkerOverlay"]);
 lstmarkeroverlay.Add((InMemoryMarkerOverlay)map.CustomOverlays["MixMarkerOverlay"]);

        

        double area = shapeArea;

        var popupdata = map.Popups[0];

        XGraphics graphics = XGraphics.FromPdfPage(page);

        int headerHeight = 70;

        string title = args["title"].ToString();

        string subTitle = args["subtitle"].ToString();

        string legend = args["legend"].ToString();

        if (Session["ShapeArea"] != null)

        {

            Area = Session["ShapeArea"].ToString();

        }

        if (legend != "undefined")

        {

    lstlegend = (new    JavaScriptSerializer()).Deserialize<List<LegendResult(args["legend"].ToString());

        } 

        try

        {

            graphics.DrawRectangle(Brushes.White, new Rectangle(0, 0, (int)page.Width, (int)headerHeight));

            graphics.DrawLine(new XPen(XColor.FromKnownColor(KnownColor.Black), 1), 0, (int)headerHeight + 2, (int)page.Width, (int)headerHeight + 1);

            graphics.DrawImage(XImage.FromFile(Server.MapPath("~/images/MoE-logo.png")), new XRect(0, 0, headerHeight,

headerHeight));

            graphics.DrawString(title, new XFont(font, 20, XFontStyle.Bold), XBrushes.Black, new XRect(0, 5, page.Width, (int)headerHeight / 3), XStringFormats.Center);

            graphics.DrawString(subTitle, new XFont(font, 16, XFontStyle.Bold), XBrushes.Black, new XRect(0, (int)headerHeight / 3,

page.Width, (int)headerHeight / 3), XStringFormats.Center);

            graphics.DrawImage(XImage.FromFile(Server.MapPath("~/images/MoE-logo.png")), new XRect(page.Width -

headerHeight, 0, headerHeight, headerHeight));

        }

        finally

        {

            graphics.Dispose();

        }

        

        int FooterHeight = 50;

        int margin = 5;

        headerHeight = headerHeight +
          2+margin;

        int MapHeight = Convert.ToInt32(page.Height - (headerHeight +
                                FooterHeight));

        pdfGeoCanvas.DrawingArea = new Rectangle(0, headerHeight, (int)page.Width,

MapHeight);

        Collection<SimpleCandidate> labelsInLayers = new Collection<SimpleCandidate>();            

        RectangleShape rect = new RectangleShape(double.Parse(args["left"].ToString()), double.Parse(args["top"].ToString()), double.Parse(args["right"].ToString()), double.Parse(args["bottom"].ToString()));

        foreach (LayerOverlay layeroverlay in lstlayeroverlay)

        {

            foreach (Layer layer in layeroverlay.Layers)

            {                    

                

                layer.Open();

pdfGeoCanvas.BeginDrawing(page, rect, map.MapUnit);

                layer.Draw(pdfGeoCanvas,

labelsInLayers);

                layer.Close();

                pdfGeoCanvas.EndDrawing();

            }

          

        }



        if (Session["ShapeArea"] != null)

        {

            try

            {

                int Xpos =Convert.ToInt32(page.Width-160);

                int Ypos = headerHeight+  MapHeight + 5;


             graphics = XGraphics.FromPdfPage(page);

                Rectangle shapeRect = new Rectangle(Xpos, Ypos,150, 20);



                graphics.DrawRectangle(new SolidBrush(ColorTranslator.FromHtml("#3F4B5B")),                             Rectangle.Round(shapeRect));

                graphics.DrawString("Shape Area:  " + Area + "km²", new XFont(font,             10,XFontStyle.Regular),XBrushes.White, shapeRect, XStringFormats.TopCenter);

               

            }

            finally

            {

                graphics.Dispose();

            }

        }

        try

        {

            graphics = XGraphics.FromPdfPage(page);

            double xpos = page.Width - 48;

            int ypos = headerHeight + 5;

 
      graphics.DrawImage(XImage.FromFile(Server.MapPath("~/images/narrow.png")),  new XRect(xpos, ypos,30,30));

          

        }

        finally {

            graphics.Dispose();

        }

       

        headerHeight = headerHeight + 10;

        int YFooter = headerHeight + MapHeight+2;

        int HFooter = Convert.ToInt32(page.Height - YFooter);

        int counter = 1;

        if (legend != "undefined")

        {

   
    foreach (var data in lstlegend)

            {

                try

                {

                    graphics = XGraphics.FromPdfPage(page);

                    double rectX = page.Width /5;

                    graphics.DrawRectangle(new SolidBrush(ColorTranslator.FromHtml(data.Color)),

new XRect(rectX + counter - 10,
YFooter, 8, 8));

                    //////////to make

boundaries fo the rows

                    //graphics.DrawRectangle(new

XPen(XColor.FromKnownColor(KnownColor.Black), .5), new XRect(rectX - 12,
YFooter + counter-2, 100, 27));

graphics.DrawString(data.Start.ToString() + " - " +
data.End.ToString(), new XFont(font, 7, XFontStyle.Regular),

                      XBrushes.Black, new XRect(rectX + counter,

YFooter, 17, 15), XStringFormats.TopLeft);

                    ////////////to display

in table decrease increment in counter that is 60

                    counter = counter + 10;



                }

                finally

                {

                    graphics.Dispose();

                }

            }

        }

        

        return VirtualPathUtility.ToAbsolute(filepath);

    }

Please mention if i am wrong somewhere

Regards

Hi Waha,

For print scale bar, please use ScaleBarPrinterLayer class, here is a sample, http://wiki.thinkgeo.com/wiki/map_suite_webapi_printing .
Please check the part of export PDF and modify the code to achieve your needs.

If it still doesn’t work, could you please append more information, such as Exception StackTrace, Call Stack, marker details.

Hope it can help you.

Thanks,
Emil.

Hi
I looked into this code but cant implement this in my print function
I added scale bar like this
ScaleBarAdornmentLayer adormentLayer = new ScaleBarAdornmentLayer();
adormentLayer.Location = AdornmentLocation.LowerLeft;
adormentLayer.UnitFamily = UnitSystem.Metric;
map.AdornmentOverlay.Layers.Add(“ScaleBar”,adormentLayer);
but i cant access it in my print function in any way the link u mentioned for adding scale bar layer even tried that also but where would i get those ScaleBarLayers when i did not even created it
Its ScaleBarAdornmentLayer what is being added on map for showing scalebar
Secondly,
The way i looped through layers and drawn the map in this code

       foreach (LayerOverlay layeroverlay in lstlayeroverlay)
        {
                  foreach (Layer layer in layeroverlay.Layers)
                 {                    
                
                layer.Open();
                pdfGeoCanvas.BeginDrawing(page, rect, map.MapUnit);
                layer.Draw(pdfGeoCanvas, labelsInLayers);
                layer.Close();
                pdfGeoCanvas.EndDrawing();
            }
          
        }

I need to know how can i access marker feature after this to make all markers visible in print window I tried making list off all three layers i made in InMemoryFeatureLayer but still no markers are shown while printing,This is the error that comes when i loop on InMemoryFeatures

     foreach (InMemoryMarkerOverlay markeroverlay in lstmarkeroverlay)
        {
            
           foreach (FeatureSource markerlayers in **markeroverlay.FeatureSource**)
            {
                
            }

I want to draw markers on PDFGeo Canvas using these features
Please help … and mention if im wrong at some point
Regards

Hi Waha,

Attached is a sample which shows how to print scale line and marker.
Please view the sample, and you can modify it follow your requirement.
Mvc_MapSuite-Print-Sample.zip (2.5 MB)

For “The given key was not present in the dictionary”, please check the name of CustomOverlay you want, it means there is no CustomOverlay called the name in the map.

For scale line missing, if the print extent bigger that the max-extent of the currently map unit, the scale line will be hidden. example DecimalDegree, the max-extent is (-180, 90, 180, -90) [minX, maxY, maxX, minY].

For InMemoryMarkerOverla, in the MVC Edition, the marker is loaded by JavaScript on the client, so we should convert it to InMemoryFeatureLayer, and use PointStyle to print the marker icon. More details please check the sample out.

Wish that’s helpful.

Thanks,
Emil

Hi

I added scale bar on the map properly as per my requirement,
but still working on markers to print
I’ll look into the sample u sent and will report you if still i face any issue

Regards
Waha Ali

Hi Waha,

We will keep our eyes on this thread.

Thanks,
Emil

Hi

Thanks alot for yout help Emil
I did marker display also in print function
One thing i just wana ask for knowledge
Can u explain what these lines mean …
pointStyle.XOffsetInPixel = -10.5f;
pointStyle.YOffsetInPixel = -25f;
and secondly i cant resize or change the size of these pins
If u can help i’ll be very thankful Emil

Regards

Hi Waha,

You are welcome.

The XOffsetInPixel and YOffsetInPixel are useful to allow you move the icon(image) a few pixels.
As we know, the anchor point(such as the pin tip) in the pictures are different, so we need to move the icon to make the anchor match the coordinate of the marker on the map. As shown below:
Before: without XOffsetInPixel and YOffsetInPixel, the center of icon is match the coordinate of the marker on the map

After: set the YOssetInPixel of half the height of the left icon. because the anchor of the icon is in the bottom-center

Here is a property named ‘ImageScale’ of PointStyle, this property allows you to scale the image up and down depending on how large or small you want it. It can be changed dynamically, so you could change it at every scale level to resize the bitmap based on the current scale. A scale of 1 would be the original size, while a scale of 2 would double the size. A scale of .5 would reduce the size of the image by half, and so on.

Thanks,
Emil

Hi

Thanks Alot for ypur support Emil…
I have done all tasks … I will share my code on forum once i complete with proper commenting if anyone else needs help

Thnks

Hi Waha,

You are welcome,

Thanks in advance,

Thanks,
Emil.

hi
Need some answers
i printed the map with provinces name correctly
but when i changed the language it displays correctly in map
But displays ??? instead of province names in that language
I am sending a files for u to understand

MapSuitePDFMap_636287203389683576.pdf (1.7 MB)

Any help regarding this

Hi Waha,

The render on map and print on PDF is not supported by the same class. I guess that’s because the target text hadn’t been recognition by the PDF geocanvs.

Please try to set System.Threading.Thread.CurrentThread.CurrentCulture to see whether that’s work for you. If that’s not helpful, please upload a simple sample data so we can test based on that and see whether it’s a bug.

Regards,

Don

hi Don

this is how we are changing culture while loading map

if (settings.getLayerLanguage() == tblSetting.eLanguages.Dari || settings.getLayerLanguage() == tblSetting.eLanguages.Pashto)
{
provinces.Encoding = Encoding.GetEncoding(1256);
}

Regards

Hi Waha,

That means you have set the encoding but still render text as “???” right?

So could you please sent us a test sample, or at least a test data so we can work on that?

Regards,

Don

Hi

Yes it pdfExtension Issue Don. I am sending u the files with code
I am trying to print dari or pushto language in pdf map
The library pdf sharp and pdfExtension you are using for pdf conversion do not support these languages and thus display ???
I tried unicode to diplay these language but it not showing the exact word i want
Even if i get my required result how could i access labels of all provinces and then convert then to their respective language … this is really odd logic to implement
Secondly I tried iTextSharp library for pdf conversion but it also donot support pdfgeocanvas to be printed thus im stucked in that also
Could you please check if u could do something as we have to deliver the project to our client in one or two days
Here are the related files of code
PrintFunction.txt (26.1 KB)
Index LanguageSelectionCode.txt (19.8 KB)

Please have a look and help in this
Regards
Waha Ali

Hello

Thinkgeo i am waiting for your reply
I need the answers even if we cant implement it make it clear so that we can report to our clients what is possible and what is not

Regards
Waha Ali

Hi Waha,

Our developer hadn’t reproduced your exception without your data. Our developer created a sample based on your code, then tested some data which from other user in different languages, but all of them render correct.

We cannot attach the data from other user in project, so it’s just an English data now, please try your data with sample project, if your data can reproduce that please build a small sample data and upload it, which should be helpful.

MVCApp.zip (405.9 KB)

Thanks,