This is a migrated thread and some comments may be shown as answers.

Display Shapes / Polygons on Map in Report

6 Answers 129 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Jeremy
Top achievements
Rank 1
Jeremy asked on 28 Apr 2016, 07:49 AM

How do I display shapes on a map? I have a list of co-ordinates in WKT format that make up simple polygons. I want to fill each polygon with a colour and display it on a map for the report.

Do I use a choropleth, or a ShapeMapSeries, or something else?

I've tried following this documentation and doing it programmatically, but I get this unhelpful error:

An error has occurred while rendering the report: System.NullReferenceException: Object reference not set to an instance of an object.
   at Telerik.Reporting.XamlRendering.DocumentWriting.PrimitiveWriter.WriteText(TextElement textElement)
   at Telerik.Reporting.XamlRendering.DocumentWriting.PrimitiveElementWriter.Visit(TextElement textElement)
   at Telerik.Reporting.Processing.Primitives.TextElement.Accept(PrimitiveElementVisitor visitor)
   at Telerik.Reporting.XamlRendering.DocumentWriting.XamlGraphWriter.Write(PrimitiveElement primitiveElement)
   at Telerik.Reporting.Processing.GraphWriter.<WriteGraphArea>b__4(PrimitiveElement a)
   at Telerik.Reporting.EnumerableExtensions.ForEach[T](IEnumerable`1 source, Action`1 action)
   at Telerik.Reporting.Processing.GraphWriter.WriteGraphArea(GraphArea graphArea)
   at Telerik.Reporting.Processing.GraphWriter.Write(Graph g)
   at Telerik.Reporting.XamlRendering.DocumentWriting.GraphWriter.WriteDataItemContent(LayoutElement element, ElementPageInfo pageInfo)
   at Telerik.Reporting.XamlRendering.DocumentWriting.DataItemWriter.WriteContent(LayoutElement element, ElementPageInfo pageInfo)
   at Telerik.Reporting.XamlRendering.XamlWriter.WriteStartElement(LayoutElement element, ElementPageInfo pageInfo)
   at Telerik.Reporting.BaseRendering.PageHandler.Telerik.Reporting.Paging.IPageHandler.StartElement(LayoutElement element, ElementPageInfo info)
   at Telerik.Reporting.Paging.PageStartElement.AddToPage(IPageHandler handler)
   at Telerik.Reporting.Paging.PageElementLayer.AddToPage(IPageHandler handler)
   at Telerik.Reporting.Paging.PageElementManager.AddToPage(IPageHandler handler)
   at Telerik.Reporting.Paging.PageCompositionBase.AddElementsToPage()
   at Telerik.Reporting.Paging.PageCompositionBase.SendPhysicalPages()
   at Telerik.Reporting.Paging.PageCompositionBase.OutputPage()
   at Telerik.Reporting.Paging.PageCompositionBase.CreatePages()
   at Telerik.Reporting.Paging.PagerBase.Telerik.Reporting.Paging.IPager.CreatePages(IPageHandler handler, Report report)
   at Telerik.Reporting.BaseRendering.RenderingExtensionBase.Render(Report report, Hashtable renderingContext, Hashtable deviceInfo, CreateStream createStreamCallback, EvaluateHeaderFooterExpressions evalHeaderFooterCallback)

 

Here is an example of the code I'm using:

ObservableCollection<PrettyShape> data = GetTestData();
 
var myReport = new Report();
var detail = new DetailSection { KeepTogether = true };
var testGroup = new MapGroup();
var detailPanel = new Panel
{
    Docking = DockingStyle.Top,
    Size = new SizeU(Unit.Pixel(600), Unit.Pixel(400)),
    Items =
    {
        new Map
        {
            Size = new SizeU(Unit.Pixel(600), Unit.Pixel(450)),
            Location = new PointU(Unit.Pixel(0), Unit.Pixel(50)),
            TileProvider = new GenericTileProvider { UrlTemplate = "url of tile provider goes here - tested in WPF RadMap" },
            Projection = new MercatorProjection(),
            DataSource = data,
            Series =
            {
                new ShapeMapSeries
                {
                    ShapeMapGroup = new ShapeMapGroup(),
                    SeriesGroup = testGroup,
                    ColorData = "=Fields.FillColour",
                    SourceType = new WellKnownTextSourceType { SpatialField = "=Fields.BoundaryPoints" }
                }
        },
        SeriesGroups = { testGroup }
}
detail.Items.Add(detailPanel);
myReport.Items.Add(detail);
 
MyReportViewer.ReportSource = new InstanceReportSource { ReportDocument = myReport };
MyReportViewer.RefreshReport();

 

and here is the data object:

public class PrettyShape
{
  public string BoundaryPoints { get; set; }
  public string FillColour
  {
    get
    {
      //various logic
      return "LimeGreen";
    }
  }
}

 

ObservableCollection<PrettyShape> GetTestData()

{

  var list = new List<PrettyShape>

  {

    new PrettyShape{ BoundaryPoints = "POLYGON ((-22.635025359284 118.120505304517, -22.635025359284 118.103713989258, -22.64653164056320 118.103713989258, -22.64653164056320 118.120505304517))" }

  };

  return new ObservableCollection<PrettyShape>(list);

}

6 Answers, 1 is accepted

Sort by
0
Jeremy
Top achievements
Rank 1
answered on 29 Apr 2016, 05:13 AM
OK I fixed the Object reference not set to an instance of an object. error. It seems the Attribution property of the TileProvider doesn't have a default value, so now I give it an empty string. Pretty sure that's a bug.

I still cannot display anything using a ShapeMapSeries programmatically. The map displays and the data works fine using a PointMapSeries. Following the documentation http://docs.telerik.com/reporting/maphowtoaddshapemapseriestothemapitem in Step 2 how do I create a new ShapeMapGroup from scratch in the Report Designer?
0
Stef
Telerik team
answered on 03 May 2016, 08:27 AM
Hi Jeremy,

Please use the Map Wizard to generate a report in the integrated in Visual Studio Report Designer - How to: Create a Map with BarChart series using CSV data source.
At the end you will have all the required settings serialized in the report's designer.cs(vb) file. The auto-generated code can be further modified for usage at run-time. The article also includes details how to display custom information on data points.

There is also a ready example installed by default under C:\Program Files (x86)\Telerik\Reporting Q1 2016\Examples search for ReportLibrary/Advanced/OlympicMedalsByNationalTeams.


The report generated/modified in code can be verified by a report designer after serializing the Telerik.Reporting.Report object in XML (TRDX file).


If you need further help, please open a support ticket and send us a demo project that illustrates your settings.

Regards,
Stef
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Jeremy
Top achievements
Rank 1
answered on 03 May 2016, 08:45 AM

Thanks for your reply Stef

Are you saying that the integrated Visual Studio Report Designer has different capabilities to the stand-alone Report Designer? Because the Map Wizard in the stand-alone designer doesn't allow me to ignore the Series, Size or Categories. The data structure I have to work with (shown in the original post) doesn't really fit. It would seem to fit in a ShapeMapSeries - but that option isn't given.

0
Jeremy
Top achievements
Rank 1
answered on 03 May 2016, 01:09 PM
To make it clearer, I am trying to replicate in Reporting this existing functionality in the WPF Map: http://docs.telerik.com/devtools/wpf/controls/radmap/features/information-layer/map-shapes#mappolygon
0
Katia
Telerik team
answered on 05 May 2016, 02:09 PM
Hello Jeremy,

I just updated your support ticket related to this question.

On a side note, we try to monitor forums, but if it is an emergency, please use the support ticketing system that guarantees you a response by Telerik representative in the time frame specified by your support subscription.

Thank you for your understanding and we hope the information is helpful.


For anyone interested, you can find attached the demo provided in the support ticket and a quote from the response:

"Check the sample project attached demonstrating how to design polygons for the Map item using ShapeMapSeries.
In Polygons.Designer.cs file you can see how the ShapeMapSeries are generated with code.

Again, it is our strong recommendation to use Map Wizard. To be able to access the fields from your data object in Map Wizard you can use ObjectDataSourceComponent as demonstrated in the report attached.

You might need to run the Upgrade Wizard before running the demo to downgrade Telerik Reporting references to the version installed on your machine."



Regards,
Katia
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Jeremy
Top achievements
Rank 1
answered on 13 May 2016, 08:46 AM

This was solved in a support ticket, but I'll share my solution here.

Turns out the map wizard CAN'T do this, although it does provide a helpful starting point. My main problems were that I was not naming the groups - which causes a new series to be created for each shape - and trying to use the ColorPalette to conditionally display specific colours.

Data:

public class PrettyShape
{
  public string BoundaryPoints { get; set; }
  public string FillColour { get; set; }
 
  public ObservableCollection<PrettyShape> GetTestData()
  {
    return new ObservableCollection<PrettyShape>(
    new List<PrettyShape>
    {
      new PrettyShape { BoundaryPoints = "POLYGON((12.503936 41.987637, 12.615859 41.916144, 12.574660 41.812849, 12.485396 41.797494, 12.392013 41.814896, 12.384460 41.954454))", FillColour = "Green" },
      new PrettyShape { BoundaryPoints = "POLYGON((12.224471 42.159910, 12.271850 42.143111, 12.278716 42.094726, 12.238204 42.081477, 12.172973 42.112556, 12.175719 42.133437))", FillColour = "Red" }
    });
  }
}

 

Report:

var myReport = new Report();
var detailSection = new DetailSection();
var dataObject = new PrettyShape();
 
var mapGroup = new MapGroup { Name = "MapGroup1"};
var shapeMapGroupA = new ShapeMapGroup { Name = "ShapeMapGroupA", Groupings = { new Grouping("=Fields.BoundaryPoints") }, Filters = { new Filter("=Fields.FillColour", FilterOperator.Equal, "=Green")}};
var shapeMapGroupB = new ShapeMapGroup { Name = "ShapeMapGroupB", Groupings = { new Grouping("=Fields.BoundaryPoints") }, Filters = { new Filter("=Fields.FillColour", FilterOperator.Equal, "=Red") } };
 
var map = new Map
{
  DataSource = dataObject.GetTestData(),
  GeoLocationGroups = { shapeMapGroupA, shapeMapGroupB },
  Location = new PointU(Unit.Cm(0D), Unit.Cm(0D)),
  Size = new SizeU(Unit.Cm(16), Unit.Cm(9)),
  Projection = new MercatorProjection(),
  TileProvider = new GenericTileProvider
  {
    Attribution = "",
    UrlTemplate = "http://{subdomain}.mqcdn.com/tiles/1.0.0/map/{zoom}/{X}/{Y}.jpg",
    UrlSubdomains = { "otile1", "otile2", "otile3", "otile4" }
  },
  Series =
  {
    new ShapeMapSeries
    {
      Name = "SeriesA",
      ColorPalette = new ColorPalette { Colors = { Color.Green } },
      ColorData = "=1",
      SeriesGroup = mapGroup,
      ShapeMapGroup = shapeMapGroupA,
      SourceType = new WellKnownTextSourceType { SpatialField = "=Fields.BoundaryPoints" }
    },
    new ShapeMapSeries
    {
      Name = "SeriesB",
      ColorPalette = new ColorPalette { Colors = { Color.LimeGreen } },
      SeriesGroup = mapGroup,
      ShapeMapGroup = shapeMapGroupB,
      SourceType = new WellKnownTextSourceType { SpatialField = "=Fields.BoundaryPoints" }
    }
  },
  SeriesGroups = { mapGroup }
};
 
detailSection.Items.Add(map);
myReport.Items.Add(detailSection);

 

 

 

 

Tags
General Discussions
Asked by
Jeremy
Top achievements
Rank 1
Answers by
Jeremy
Top achievements
Rank 1
Stef
Telerik team
Katia
Telerik team
Share this question
or