ThinkGeo.com    |     Blog    |     Wiki    |     Support

Print Custom Overlays to PDF

What is the proper way to print custom Overlays to PDF?


I have a Google map, several Shapefiles and inMemoryMarkerOvelay on a page.


I want to print it to PDF. I am unable to use your sample code as it uses static Ovelray.


I tried to iterate through CustomOverlays and all layers but get error that  GoogleMap is not a LayerOverlay.


Help?


 


Here is the code i am using:


 


  Protected Sub btnToPdf_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim document As New PdfDocument()
        Dim page As PdfPage = document.AddPage()
        If rdlOptions.SelectedItem.Text = "Landscape" Then
            page.Orientation = PageOrientation.Landscape
        End If
        Dim pdfGeoCanvas As New PdfGeoCanvas()

        ' This allows you to control the area in which you want the 
        ' map to draw in. Leaving this commented out uses the whole page 
        'pdfGeoCanvas.DrawingArea = new Rectangle(200, 50, 400, 400); 
        Dim labelsInLayers As New Collection(Of SimpleCandidate)()
        For Each overlay As Overlay In Map1.CustomOverlays
            Dim currentOverlay As LayerOverlay = overlay
            For Each layer As Layer In currentOverlay.Layers

                Dim printExtent As RectangleShape = ExtentHelper.GetDrawingExtent(Map1.CurrentExtent, CSng(Map1.WidthInPixels), CSng(Map1.HeightInPixels))
                pdfGeoCanvas.BeginDrawing(page, printExtent, GeographyUnit.DecimalDegree)
                layer.Open()
                layer.Draw(pdfGeoCanvas, labelsInLayers)
                layer.Close()
                pdfGeoCanvas.EndDrawing()
            Next
        Next

        Dim filename As String = Directory.GetCurrentDirectory() & "\MapSuite PDF Map.pdf"
        document.Save(filename)
        OpenPdfFile(filename)
    End Sub



Jakub,



You are in the right way, but missed one thing. GoogleOverlay doesn’t inherit from LayerOverlay; it’s a single overlay which uses Google’s API and gets images directly from Google’s server, it does not go to the server-side. That means we cannot handle it with PDF printed on the server-side.



I recommend using GoogleMapsLayer instead of using GoogleOverlay; it’s a kind of layer which is added into the LayerOverlay.



Here is the code to add a GoogleMapsLayer:GoogleMapsLayer googleLayer = new GoogleMapsLayer(“Put your google key here”);
Map1.StaticOverlay.Layers.Add(googleLayer);



If you have any questions please let me know.



Thanks,

Howard



Hi Howard,


I am not sure how is that going to work as all my other overlays and Markers are on a customOverlay. Static and custom overlays cannot be mixed.


When I change your code to CustomOvelay.Add(googleOverlay) it says that the Google layer cannot be converted to Web.Overlays


I need to be able to print a base overlay (Google, Yahoo, VierualEarth) and then several loaded shapefiles and inMemoryMarkerOverlay.


What is the best way to achieve that?


Thanks,


Jakub


 



Hi Jakub,



Actually, StaticOverlay is a shortcut of using a LayerOverlay which can be added into the CustomOverlay. Here is the code for CustomOverlay:Dim googleLayer As New GoogleMapsLayer("Put your google key here")
Dim layerOverlay As New LayerOverlay("LayerId")
layerOverlay.Layers.Add(googleLayer)
// ShapeFileLayer and InMemoryLayer can be added in this overlay.



Currently, we support layer for Google and VirtualEarth but Yahoo. Please keep an eye on our web site for new features of WebEdition.



If you have more questions please let me know.



Thanks,

Howard



Still will not let me add it to Custom Overlays. same error. GoogleMapsLayer cannot be converted to WebEdition.Overlay. 
 Also, even when I remove all base overlays the Print to PDF bobms on the Marker Overlay. cannnot cast 
 ‘ThinkGeo.MapSuite.WebEdition.InMemoryMarkerOverlay’ to type ‘ThinkGeo.MapSuite.WebEdition.LayerOverlay’. 
  
 ?? 
 Thanks, 
 Jakub 


Jakub, 



I think you just be confused by our layers and overlays. Please refer to this post for more information:

gis.thinkgeo.com/Support/Dis....aspx#5007



Generally speaking, LayerOverlay, MarkerOverlay, GoogleOverlay are in the same level of class inheritance. You cannot cast MarkerOverlay to LayerOverlay.



Currently, only LayerOverlay in the CustomOverlays can print to PDF.



After reading the post above, I think you should know that GoogleMapsLayer is a layer while GoogleOverlay is an Overlay. Map object maintains many overlays while one LayerOverlay maintains many layers, and LayerOverlay is the one you add the GoogleMapsLayer to.



Now the rest question is MarkerOverlay. MarkerOverlay is an overlay which cannot cast to LayerOverlay, so that, markers cannot print to PDF. We recommend you to use PointStyle on an InMemoryFeatureLayer to simulate a MarkerOverlay, and then it can be printed to PDF.



So you code should be like:Protected Sub btnToPdf_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim document As New PdfDocument()
    Dim page As PdfPage = document.AddPage()
    If rdlOptions.SelectedItem.Text = "Landscape" Then
        page.Orientation = PageOrientation.Landscape
    End If
    Dim pdfGeoCanvas As New PdfGeoCanvas()
    
    ' This allows you to control the area in which you want the
    ' map to draw in. Leaving this commented out uses the whole page
    'pdfGeoCanvas.DrawingArea = new Rectangle(200, 50, 400, 400);
    Dim labelsInLayers As New Collection(Of SimpleCandidate)()
    For Each overlay As Overlay In Map1.CustomOverlays
        Dim currentOverlay As LayerOverlay = TryCast(overlay, LayerOverlay)
        If currentOverlay IsNot Nothing Then
            For Each layer As Layer In currentOverlay.Layers
                Dim printExtent As RectangleShape = ExtentHelper.GetDrawingExtent(Map1.CurrentExtent, CSng(Map1.WidthInPixels), CSng(Map1.HeightInPixels))
                pdfGeoCanvas.BeginDrawing(page, printExtent, GeographyUnit.DecimalDegree)
                layer.Open()
                layer.Draw(pdfGeoCanvas, labelsInLayers)
                layer.Close()
                pdfGeoCanvas.EndDrawing()
            Next
        End If
    Next
    
    Dim filename As String = Directory.GetCurrentDirectory() & "\MapSuite PDF Map.pdf"
    document.Save(filename)
    OpenPdfFile(filename)
End Sub



Any more questions please let me know.



Thanks,

Howard

 



So essentiallyI cannot print what is displayed on screen into PDF, right? 
 Is there a plan to introduce this functionality? 
  
 Thanks, 
 jakub 


Jakub, 
  
 Not exactly; that’s depending on what type of overlay you are using. I mean only the LayerOverlay can be printed into PDF; while the other overlays such as GoogleOverlay, YahooOverlay, VirtualEarthOverlay are using the 3rd part client library which we cannot handle on the server side; LayerOverlay is an overlay which renders map on the server side, so that, we can handle all the rendering on the server. 
  
 In your application, if all your overlays are type of LayerOverlay, it can be printed into PDF. That’s what I mentioned to switch using GoogleOverlay to GoogleMapsLayer which can be added into LayerOverlay. 
  
 You gave us a good suggestion; our new user usually ask some questions about the layer and overlay. I think we can have some white paper for it. 
  
 If you have any questions please let me know. 
  
 Thanks, 
 Howard

Hi Howard, 
 Thanks for explanation it is clearer now. 
 I switched to GoogleMapsLayer and this is what I get when printing to PDF. It displays fine. 
 ERROR: 
 The map unit you are using is not compatable with the GoogleLayer .  Make sure you are using Meters and that your projection is 90013 to ensure compatability. Parameter name: canvas.MapUnit
 
  
 My MapUnit is Meter and projection is EPSG:900913 
  
 What is wrong? 
  
 also I really need to show the markers in PDF. What is the PointStyle on an InMemoryFeatureLayer and how do i use it to load thousands of points from a database? 
 Thanks 
 Jakub 


Jakub,



Google’s projection EPSG:900913 and its GeographyUnit is meter. So the code below should be the correct one.pdfGeoCanvas.BeginDrawing(page, printExtent, GeographyUnit.Meter)


The attached sample specify how to imitate the markers using InMemoryFeatureLayer.



If you have any questions , please let me know.



Thanks,

Howard

 



916-DisplayASimpleMap.aspx.vb (2.39 KB)

OK,


I started using the LayerOvelay for my shapefiles.



        
  1. There are two issues. The Google Logos and their text are all over the base layer (right in the middle of the screen) is there a way to remove them or move them to the bottom?

  2.     
  3. The shapefiles load into proper location on the screen (see TGMapScreenCap) but are in the wrong location in the PDF printout (See TGMapPDFPrint). See the yellow patches on the east coas that are extending into the ocean = WRONG


Is there a way to align them properly for the printout?


Thanks


Jakub


 


 



936-TGMapPDFprint.jpg (78.9 KB)
937-TGMapScreenCap.jpg (256 KB)

Jakub, 
  
 1. We are using Google Static API which has the size limits that cannot beyond 512 pixel. So currently we cannot remove it. Or we can have a logic to hide it; but currently, it’s not on the schedule. We’ll let you know when we have a fix. 
  
 2. Through your screenshot and code, I guess the printing width and height is different showing on the web page. Is the map’s width and height 100%? Or please provide us a quick sample to recreate this issue. 
  
 PDF does have some bugs now; I’ll let you know when I recreate it. 
  
 Any questions please let me know. 
  
 Thanks, 
 Howard

Any update on having the PDf print the overlays in the right location?


Client is really unhappy about that.


 


Thanks,


jakub



Jakub, 
  
 We cannot figure out the issue through your screenshot. It may caused by shape data, width and height ratio, or code and so on. 
  
 So please provide us your quick sample so that we can recreate your issue first. 
  
 Sorry for the inconvenience. 
  
 Thanks, 
 Howard

It is not only the shape data, it shows the markers out of position as well. Height and width are set to square. for screen. 

There is another issue. when following statement is used on the shapefile layers 




plumeLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateHatchStyle(GeoHatchStyle.LightDownwardDiagonal, GeoColor.GetRandomGeoColor(RandomColorType.All), GeoColor.StandardColors.Transparent, GeoColor.GetRandomGeoColor(RandomColorType.All)) 





the PDF routine errors out on this line 



pdfGeoCanvas.EndDrawing() 



with error "Specified Method is not supported". 



 



Here is the code I am using to generate PDF - pretty much straight out of your sample.


 



   Protected Sub btnToPdf_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim document As New PdfDocument()
        Dim page As PdfPage = document.AddPage()
        If rdlOptions.SelectedItem.Text = "Landscape" Then
            page.Orientation = PageOrientation.Landscape
        End If
        Dim pdfGeoCanvas As New PdfGeoCanvas()

        ' This allows you to control the area in which you want the
        ' map to draw in. Leaving this commented out uses the whole page
        'pdfGeoCanvas.DrawingArea = new Rectangle(200, 50, 400, 400);
        Dim labelsInLayers As New Collection(Of SimpleCandidate)()
        For Each overlay As Overlay In Map1.CustomOverlays
            Dim currentOverlay As LayerOverlay = TryCast(overlay, LayerOverlay)
            If currentOverlay IsNot Nothing Then
                For Each layer As Layer In currentOverlay.Layers
                    Dim printExtent As RectangleShape = ExtentHelper.GetDrawingExtent(Map1.CurrentExtent, CSng(Map1.WidthInPixels), CSng(Map1.HeightInPixels))
                  
                    pdfGeoCanvas.BeginDrawing(page, printExtent, GeographyUnit.Meter)
                    layer.Open()
                    layer.Draw(pdfGeoCanvas, labelsInLayers)
                    layer.Close()
                    pdfGeoCanvas.EndDrawing()
                Next
            End If
        Next

        Dim filename As String = Directory.GetCurrentDirectory() & "\PDFMap.pdf"
        document.Save(filename)
        Response.Redirect("../LogFilesave.aspx?z=" & filename)
       
    End Sub



Jakub, 
  
 I think the problem is that: VE’s image are fixed while the layer on top of ve is drawing by us which will fix the extent on the PDF page size. I think one solution is to set the pdf page size the same as the map’s width and height or set the drawing area for the layers which is on top of ve’s.  
  
 Here is a related post which may help. 
 gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/12/aft/6033/afv/topic/Default.aspx 
  
 Any questions please let me know. 
  
 Thanks, 
 Howard

I am using Google not VE. :) 
 Adjusting the height and width of the pdf drawing to square (same as my window) plots it to the right place, but now the shapefiles  bleed outside of the base layer. 
 I looked at the related link but was not able to convert it to VB as some of the functions do not seem to be available. 
 Can you give me a hint on how to match the print area to the map extent?  
  
 How about the error with pdfGeoCanvas.EndDrawing() mentioned in the above post? Why can’t I print hatched AreaStyles to PDF? 
  
 Thanks 
 jakub 
  
  


Hi Jakub, 
  
 Sorry for delaying your post. I recreated your issue and I’ll do some research for it andl let you know when I have an update. 
  
 Thanks, 
 Howard

Any update on this?  
 I do not necessarily need to create hatch styles, if I could set the opacity of the solid style so it is semi-transparent. 
 Do not seem to be able to to it. 
  layerOverlay.Opacity = 50 does nothing