How to reproduce: check the attached project, the expected behavior would be that the MapPoint object have its text painted Workaround: public partial class RadForm1 : Telerik.WinControls.UI.RadForm { public RadForm1() { InitializeComponent(); MapLayer pinsLayer = new MapLayer("Buildings Layout"); this.radMap1.Layers.Add(pinsLayer); EmptyMapProvider emptyProvider = new EmptyMapProvider(); emptyProvider.InitializationComplete += emptyProvider_InitializationComplete; this.radMap1.Providers.Add(emptyProvider); using (FileStream seatsStream = File.OpenRead(@"..\..\shapes-new\Label_Pk_Boulou2.shp")) { using (FileStream seatsDataStream = File.OpenRead(@"..\..\shapes-new\Label_Pk_Boulou2.dbf")) { ShapeFileReaderParameters parameters = new ShapeFileReaderParameters(); parameters.ShapeStream = seatsStream; parameters.DbfStream = seatsDataStream; //parameters.CoordinateConverter = new EPSG900913Converter(); ShapeFileReader reader = new ShapeFileReader(); List<MapVisualElement> elements = reader.Read(parameters); foreach (var item in elements) { item.Text = Convert.ToString(((IExtendedData)item).ExtendedData["Text"]); } this.radMap1.Layers["Buildings Layout"].AddRange(elements); } } } }
To reproduce: public RadForm1() { InitializeComponent(); this.radMap1.ToolTipTextNeeded += radMap1_ToolTipTextNeeded; BingRestMapProvider bingProvider = new Telerik.WinControls.UI.BingRestMapProvider(); bingProvider.UseSession = true; bingProvider.BingKey = bingKey; this.radMap1.Providers.Add(bingProvider); //add a layer to display the route this.radMap1.MapElement.Layers.Add(new MapLayer()); RouteRequest request = new RouteRequest(); request.DistanceUnit = DistanceUnit.Kilometer; request.Options.Mode = TravelMode.Driving; request.Options.Optimization = RouteOptimization.Time; request.Options.RouteAttributes = RouteAttributes.RoutePath; request.Options.RouteAvoidance = RouteAvoidance.None; request.Waypoints.Add("Paris, France"); request.Waypoints.Add("Madrid, Spain"); bingProvider.CalculateRouteCompleted += BingProvider_RoutingCompleted; bingProvider.CalculateRouteAsync(request); } private void radMap1_ToolTipTextNeeded(object sender, Telerik.WinControls.ToolTipTextNeededEventArgs e) { Console.WriteLine(sender); } private void BingProvider_RoutingCompleted(object sender, RoutingCompletedEventArgs e) { List<PointG> pts = new List<PointG>(); Telerik.WinControls.UI.Map.PointG startPoint = new Telerik.WinControls.UI.Map.PointG(e.Route.RoutePath.Line.Coordinates.First()[0], e.Route.RoutePath.Line.Coordinates.First()[1]); pts.Add(startPoint); Telerik.WinControls.UI.Map.PointG endPoint = new Telerik.WinControls.UI.Map.PointG(e.Route.RoutePath.Line.Coordinates.Last()[0], e.Route.RoutePath.Line.Coordinates.Last()[1]); pts.Add(endPoint); MapPolyline mapPolyline = new MapPolyline(pts); mapPolyline.BackColor = Color.Red; mapPolyline.BorderColor = Color.Red; mapPolyline.BorderWidth = 5; this.radMap1.MapElement.Layers[0].Add(mapPolyline); PointG midPoint = new PointG((startPoint.Latitude + endPoint.Latitude) / 2d, (startPoint.Longitude + endPoint.Longitude) / 2d); MapLabel westernLabel = new MapLabel(midPoint, "My label") { BackColor = Color.FromArgb(122, 255, 0, 0) }; this.radMap1.MapElement.Layers[0].Add(westernLabel); } Workaround: public class CustomMapPolyline : MapPolyline { List<GraphicsPath> paths; public CustomMapPolyline(IEnumerable<PointG> points) : base(points) { } public override void ViewportChanged(IMapViewport viewport, ViewportChangeAction action) { base.ViewportChanged(viewport, action); FieldInfo fi = typeof(MapPolyline).GetField("paths", BindingFlags.Instance | BindingFlags.NonPublic); this.paths = (List<GraphicsPath>)fi.GetValue(this); } public override bool HitTest(PointG pointG, PointL pointL, IMapViewport viewport) { using (Pen pen = new Pen(this.BorderColor, this.BorderWidth)) { foreach (GraphicsPath path in this.paths) { if (path.IsOutlineVisible(pointL.X, pointL.Y, pen)) { return true; } } } return false; } }
Workaround: Public Class MyLocalMapProvider Inherits LocalMapProvider Public Overrides Sub ViewportChanged(viewport As IMapViewport, action As ViewportChangeAction) If Not Me.Initialized Then Me.Initialize() Return End If Dim tilesToDraw As List(Of MapVisualElement) = DirectCast(Me.GetType().BaseType.GetField("tilesToDraw", BindingFlags.Instance Or BindingFlags.NonPublic).GetValue(Me), List(Of MapVisualElement)) Dim numOfTilesX As Integer = CInt(Math.Ceiling(CDbl((viewport.ViewportInPixels.Width)) / Me.TileSize.Width)) + 2 Dim numOfTilesY As Integer = CInt(Math.Ceiling(CDbl((viewport.ViewportInPixels.Height)) / Me.TileSize.Height)) + 2 Dim maxNumberOfTilesY As Integer = If((viewport.ZoomLevel = 1), 2, (viewport.ZoomLevel - 1) << 2) numOfTilesY = Math.Min(numOfTilesY, maxNumberOfTilesY) Dim topLeftTile As Point = MapTileSystemHelper.PixelXYToTileXY(-viewport.PanOffset.Width, -viewport.PanOffset.Height) Dim numberOfTiles As Integer = 2 << (viewport.ZoomLevel - 1) Dim startX As Integer = CInt(viewport.PanOffset.Width) Mod Me.TileSize.Width Dim startY As Integer = CInt(viewport.PanOffset.Height) Mod Me.TileSize.Height If startX > 0 Then startX -= Me.TileSize.Width End If For i As Integer = 0 To numOfTilesY - 1 For j As Integer = 0 To numOfTilesX - 1 Dim x As Integer = startX + j * Me.TileSize.Width Dim y As Integer = startY + i * Me.TileSize.Height Dim tileX As Integer = (topLeftTile.X + j) Mod numberOfTiles Dim tileY As Integer = (topLeftTile.Y + i) Mod numberOfTiles If tileX < 0 Then tileX += numberOfTiles End If tilesToDraw.Add(New MapTile(Me.GetTileImage(tileX, tileY, viewport.ZoomLevel), New Rectangle(New Point(x, y), Me.TileSize))) Next Next End Sub End Class
You can find attached a sample project, video, demonstrating the steps and a screenshot of the error. Workaround: public class MyMapVisualElementFactory : MapVisualElementFactory { public override MapVisualElement CreatePolyline(Collection<PointG> points) { return new MyMapPolyline(points); } } public class MyMapPolyline : MapPolyline { private FieldInfo pathsField; private FieldInfo boundingRectsField; private FieldInfo isInViewportField; public MyMapPolyline(Collection<PointG> points) : base(points) { this.pathsField = typeof(MapPolyline).GetField("paths", BindingFlags.Instance | BindingFlags.NonPublic); this.boundingRectsField = typeof(MapPolyline).GetField("boundingRects", BindingFlags.Instance | BindingFlags.NonPublic); this.isInViewportField = typeof(MapPolyline).GetField("isInViewport", BindingFlags.Instance | BindingFlags.NonPublic); } public override void ViewportChanged(IMapViewport viewport, ViewportChangeAction action) { if ((action & ViewportChangeAction.All) == action) { long mapSize = MapTileSystemHelper.MapSize(viewport.ZoomLevel); List<GraphicsPath> paths = new List<GraphicsPath>(); List<RectangleL> boundingRects = new List<RectangleL>(); long start = viewport.PanOffset.Width; int maxWraparounds = 1; while (start + mapSize < viewport.ViewportInPixels.Width) { maxWraparounds++; start += mapSize; } for (int i = -1; i <= maxWraparounds; i++) { GraphicsPath path = new GraphicsPath(); List<PointF> drawPoints = new List<PointF>(); foreach (PointG p in this.Points) { PointL pixel = MapTileSystemHelper.LatLongToPixelXY(p.Latitude, p.Longitude, viewport.ZoomLevel); drawPoints.Add(new PointF(pixel.X + i * mapSize, pixel.Y)); } path.AddLines(drawPoints.ToArray()); RectangleF rect = path.GetBounds(); RectangleF view = new RectangleF(viewport.ViewportInPixels.X, viewport.ViewportInPixels.Y, viewport.ViewportInPixels.Width, viewport.ViewportInPixels.Height); if (rect.IntersectsWith(view)) { paths.Add(path); } boundingRects.Add(new RectangleL((long)rect.X, (long)rect.Y, (long)rect.Width, (long)rect.Height)); } this.pathsField.SetValue(this, paths); this.boundingRectsField.SetValue(this, boundingRects); } if (action != ViewportChangeAction.None) { this.isInViewportField.SetValue(this, false); List<RectangleL> boundingRects = this.boundingRectsField.GetValue(this) as List<RectangleL>; foreach (RectangleL rect in boundingRects) { if (viewport.ViewportInPixels.IntersectsWith(rect)) { this.isInViewportField.SetValue(this, true); } } } } } public class MyMapVisualElementFactory : MapVisualElementFactory { public override MapVisualElement CreatePolyline(Collection<PointG> points) { return new MyMapPolyline(points); } } public class MyMapPolyline : MapPolyline { private FieldInfo pathsField; private FieldInfo boundingRectsField; private FieldInfo isInViewportField; public MyMapPolyline(Collection<PointG> points) : base(points) { this.pathsField = typeof(MapPolyline).GetField("paths", BindingFlags.Instance | BindingFlags.NonPublic); this.boundingRectsField = typeof(MapPolyline).GetField("boundingRects", BindingFlags.Instance | BindingFlags.NonPublic); this.isInViewportField = typeof(MapPolyline).GetField("isInViewport", BindingFlags.Instance | BindingFlags.NonPublic); } public override void ViewportChanged(IMapViewport viewport, ViewportChangeAction action) { if ((action & ViewportChangeAction.All) == action) { long mapSize = MapTileSystemHelper.MapSize(viewport.ZoomLevel); List<GraphicsPath> paths = new List<GraphicsPath>(); List<RectangleL> boundingRects = new List<RectangleL>(); long start = viewport.PanOffset.Width; int maxWraparounds = 1; while (start + mapSize < viewport.ViewportInPixels.Width) { maxWraparounds++; start += mapSize; } for (int i = -1; i <= maxWraparounds; i++) { GraphicsPath path = new GraphicsPath(); List<PointF> drawPoints = new List<PointF>(); foreach (PointG p in this.Points) { PointL pixel = MapTileSystemHelper.LatLongToPixelXY(p.Latitude, p.Longitude, viewport.ZoomLevel); drawPoints.Add(new PointF(pixel.X + i * mapSize, pixel.Y)); } path.AddLines(drawPoints.ToArray()); RectangleF rect = path.GetBounds(); RectangleF view = new RectangleF(viewport.ViewportInPixels.X, viewport.ViewportInPixels.Y, viewport.ViewportInPixels.Width, viewport.ViewportInPixels.Height); if (rect.IntersectsWith(view)) { paths.Add(path); } boundingRects.Add(new RectangleL((long)rect.X, (long)rect.Y, (long)rect.Width, (long)rect.Height)); } this.pathsField.SetValue(this, paths); this.boundingRectsField.SetValue(this, boundingRects); } if (action != ViewportChangeAction.None) { this.isInViewportField.SetValue(this, false); List<RectangleL> boundingRects = this.boundingRectsField.GetValue(this) as List<RectangleL>; foreach (RectangleL rect in boundingRects) { if (viewport.ViewportInPixels.IntersectsWith(rect)) { this.isInViewportField.SetValue(this, true); } } } } }
In the scenario below one should be able to access the defined UserData value in the SearchCompleted event handler How to reproduce: protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.radMap1.ShowSearchBar = true; BingRestMapProvider bingProvider = this.radMap1.Providers[0] as BingRestMapProvider; this.radMap1.MapElement.SearchBarElement.SearchProvider = bingProvider; this.radMap1.MapElement.SearchBarElement.SearchProvider.SearchCompleted += BingProvider_SearchCompleted; } private void BingProvider_SearchCompleted(object sender, SearchCompletedEventArgs e) { Telerik.WinControls.UI.Map.RectangleG allPoints = new Telerik.WinControls.UI.Map.RectangleG(double.MinValue, double.MaxValue, double.MaxValue, double.MinValue); this.radMap1.Layers["Pins"].Clear(); foreach (Telerik.WinControls.UI.Map.Bing.Location location in e.Locations) { Telerik.WinControls.UI.Map.PointG point = new Telerik.WinControls.UI.Map.PointG(location.Point.Coordinates[0], location.Point.Coordinates[1]); MapPin pin = new MapPin(point); pin.Size = new System.Drawing.Size(20, 40); pin.BackColor = Color.Red; pin.ToolTipText = location.Address.FormattedAddress; this.radMap1.MapElement.Layers["Pins"].Add(pin); allPoints.North = Math.Max(allPoints.North, point.Latitude); allPoints.South = Math.Min(allPoints.South, point.Latitude); allPoints.West = Math.Min(allPoints.West, point.Longitude); allPoints.East = Math.Max(allPoints.East, point.Longitude); } if (e.Locations.Length > 0) { if (e.Locations.Length == 1) { this.radMap1.BringIntoView(new Telerik.WinControls.UI.Map.PointG(e.Locations[0].Point.Coordinates[0], e.Locations[0].Point.Coordinates[1])); } else { this.radMap1.MapElement.BringIntoView(allPoints); this.radMap1.Zoom(this.radMap1.MapElement.ZoomLevel - 1); } } else { RadMessageBox.Show("No result found for the provided search query!"); } } Telerik.WinControls.UI.Map.Bing.SearchRequest request; private void radButton1_Click(object sender, EventArgs e) { Telerik.WinControls.UI.MapLayer pinsLayer = new MapLayer("Pins"); this.radMap1.Layers.Add(pinsLayer); request = new SearchRequest(); request.Query = "San Marino"; request.SearchOptions.Count = 10; request.SearchOptions.QueryParse = true; request.UserData = "Tooltip"; BingRestMapProvider bingProvider = this.radMap1.Providers[0] as BingRestMapProvider; bingProvider.SearchAsync(request); } Workaround: if possible cache the data to be accessed at a later stage
The ShapeFileReader fails in its ReadDbfRecord method:
using (MemoryStream shapeStream = new MemoryStream(File.ReadAllBytes(@"C:\Users\dyordano\Downloads\84aa4699-f436-4b7e-b029-e353fdab0411_shapefile-before-modification\asseuappareil.shp")))
{
using (MemoryStream dbfStream = new MemoryStream(File.ReadAllBytes(@"C:\Users\dyordano\Downloads\84aa4699-f436-4b7e-b029-e353fdab0411_shapefile-before-modification\asseuappareil.dbf")))
{
ShapeFileReaderParameters parameters = new ShapeFileReaderParameters();
parameters.ShapeStream = shapeStream;
parameters.DbfStream = dbfStream;
ShapeFileReader reader = new ShapeFileReader();
List<MapVisualElement> elements = reader.Read(parameters);
}
}
Hello,
I am using RadMap to display a KML file.
Unfortunately, it looks like RadMap is not displaying properly all the shapes (departments).
Displayed with RadMap (few holes, ie departments not displayed):
Displayed with a third party tool (all departments properly displayed):
I have attached the KML file in a zip file.
Best,
Olivier
Recently OpenStreetMap changed their tile usage policy and require UserAgent string in the web headers for accessing tile.openstreetmap.org tiles.
https://operations.osmfoundation.org/policies/tiles/
As a result, standard open street map mode does not work - no tiles are loaded and "too many requests" error is returned from the server.
RadMap's OpenStreetMapProvider needs API (event, property or similar) for easier set up of UserAgent / Referer / other headers of web requests.
Please refer to the sample project and follow the steps:
1. Run the attached application.
To reproduce:
set the clustering and add some pins upon a button click.
Workaround
Refresh with the following method:
To reproduce: The TileSize property of the LocalMapProvider is readonly. Workaround: public class CustomLocalMapProvider : LocalMapProvider { public CustomLocalMapProvider() { FieldInfo fi = typeof(LocalMapProvider).GetField("tileSize", BindingFlags.Instance | BindingFlags.NonPublic); fi.SetValue(this, new Size(200,200)); } }
https://msdn.microsoft.com/en-us/library/ff701717.aspx
Until released use the following custom implementation: public partial class RoadOnDemandForm : RadForm { public RoadOnDemandForm() { InitializeComponent(); string cacheFolder = @"..\..\cache"; BingRestMapProvider bingProvider = new MyBingRestMapProvider(); bingProvider.Culture = System.Threading.Thread.CurrentThread.CurrentCulture; bingProvider.ImagerySet = ImagerySet.Road; bingProvider.UseSession = true; bingProvider.BingKey = "YourApiKey"; LocalFileCacheProvider cache = new LocalFileCacheProvider(cacheFolder); bingProvider.CacheProvider = cache; this.radMap1.MapElement.Providers.Add(bingProvider); } } public class MyBingRestMapProvider : BingRestMapProvider { private const string ImageryMetadataServiceUri = "https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{set}?output=json&key={key}&c={culture}&dir={directory}"; protected override void InitializeImageryService() { typeof(BingRestMapProvider).GetField("tileMetadataInfo", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(this, null); try { string uriString = ImageryMetadataServiceUri; uriString = uriString.Replace("{set}", "RoadOnDemand"); uriString = uriString.Replace("{key}", string.IsNullOrEmpty(this.SessionId) ? this.BingKey : this.SessionId); uriString = uriString.Replace("{culture}", this.Culture.ToString()); uriString = uriString.Replace("{directory}", "0"); WebClient client = new WebClient(); client.DownloadStringCompleted += this.InitializeImageryMetadataCompleted; client.DownloadStringAsync(new Uri(uriString, UriKind.Absolute)); } catch (Exception ex) { throw new Exception(string.Format("Imagery Service Exception: {0}", ex.Message)); } } }
How to reproduce: public partial class Form3 : Form { public Form3() { InitializeComponent(); MapLayer pointLayer = new MapLayer("PointG"); pointLayer.ClusterStrategy = new ElementClusterStrategy(); pointLayer.ClusterDistance = 100; this.radMap1.Layers.Add(pointLayer); MapPin pin1 = new MapPin(new PointG(45d, 15d)) { BackColor = Color.Coral, ToolTipText = "Tool Tip1" }; MapPin pin2 = new MapPin(new PointG(44d, 18d)) { BackColor = Color.Coral, ToolTipText = "Tool Tip2" }; this.radMap1.Layers["PointG"].Add(pin1); this.radMap1.Layers["PointG"].Add(pin2); this.SetupProviders(); } private void radMap1_ToolTipTextNeeded(object sender, Telerik.WinControls.ToolTipTextNeededEventArgs e) { MapCluster cluster = sender as MapCluster; if (cluster != null && cluster.ClusteredItems.Count == 1) { cluster.ToolTipText = ((MapPin)cluster.ClusteredItems[0]).ToolTipText; } } private void SetupProviders() { string cacheFolder = @"..\..\cache"; BingRestMapProvider bingProvider = new BingRestMapProvider(); bingProvider.Culture = System.Threading.Thread.CurrentThread.CurrentCulture; bingProvider.ImagerySet = ImagerySet.Road; bingProvider.UseSession = true; bingProvider.BingKey = "..."; LocalFileCacheProvider cache = new LocalFileCacheProvider(cacheFolder); bingProvider.CacheProvider = cache; this.radMap1.MapElement.Providers.Add(bingProvider); bingProvider.InitializationComplete += bingProvider_InitializationComplete; } private void bingProvider_InitializationComplete(object sender, EventArgs e) { this.radMap1.BringIntoView(new PointG(45d, 15d), 5); } } Workaround: handle the ToolTipNeededEvent private void radMap1_ToolTipTextNeeded(object sender, Telerik.WinControls.ToolTipTextNeededEventArgs e) { MapCluster cluster = sender as MapCluster; if (cluster != null && cluster.ClusteredItems.Count == 1) { cluster.ToolTipText = ((MapPin)cluster.ClusteredItems[0]).ToolTipText; } }
How to reproduce: change the Windows culture to Greek and start the OSM example
How to reproduce: check the attached video Workaround: create a custom MapSearchBarElement public class MyRadMap : RadMap { public override string ThemeClassName { get { return typeof(RadMap).FullName; } } protected override RadMapElement CreateMapElement() { return new MyRadMapElement(); } } public class MyRadMapElement : RadMapElement { protected override Type ThemeEffectiveType { get { return typeof(RadMapElement); } } protected override MapSearchBarElement CreateSearchBarElement() { return new MyMapSearchBarElement(this); } } public class MyMapSearchBarElement : MapSearchBarElement { public MyMapSearchBarElement(MyRadMapElement mapElement) : base(mapElement) { } protected override Type ThemeEffectiveType { get { return typeof(MapSearchBarElement); } } protected override void SearchProviderSearchError(object sender, SearchErrorEventArgs e) { IMapSearchProvider provider = sender as IMapSearchProvider; provider.SearchCompleted -= SearchProviderSearchCompleted; provider.SearchError -= SearchProviderSearchError; if (this.ElementTree != null) { UnsubscribeToTextBoxEvents(this.SearchTextBoxElement); RadMessageBox.SetThemeName(this.ElementTree.ThemeName); RadMessageBox.Show(e.Error.Message); SubscribeToTextBoxEvents(this.SearchTextBoxElement); } } protected override void SubscribeToTextBoxEvents(RadTextBoxElement textBox) { textBox.TextChanged += OnSearchTextBoxTextChanged; textBox.KeyDown += OnSearchTextBoxKeyDown; } protected override void UnsubscribeToTextBoxEvents(RadTextBoxElement textBox) { textBox.TextChanged -= OnSearchTextBoxTextChanged; textBox.KeyDown -= OnSearchTextBoxKeyDown; } private void OnSearchTextBoxKeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { this.Search(this.SearchTextBoxElement.Text); } } }