I'm using UriImage provider as a base class to allow me to display various image files (e.g. floor plans). I don't have geographic coordinates for the images but I want to overlay data on the image relative to the image bottom left, using pixel coordinates. I've configured my provider class to use EPSG900913Projection as its spatial reference. Effectively my image should be displayed with the bottom left corner at 0,0. This is what my provider class looks like:
public class SchematicProvider : UriImageProvider, ICloneable
{
private SchematicViewModel _viewModel;
// EPSG900913Projection is a proportional projection so should work for arbitrary units (i.e. IPSC schematic maps)
private readonly EPSG900913Projection _projection = new EPSG900913Projection();
public override ISpatialReference SpatialReference => _projection;
public SchematicProvider(SchematicViewModel viewModel)
{
_viewModel = viewModel;
var mediaFileName = viewModel.GetMediaFileName();
var topLeft = new Location(6000, 0);
var bottomRight = new Location(0, 8000);
// If I don't include this line, I can't zoom in and out of the image
// but including this line makes the app crash when I click on the minimap button
GeoBounds = new LocationRect(topLeft, bottomRight);
Uri = new Uri(mediaFileName);
}
public new object Clone()
{
var provider = new SchematicProvider(_viewModel);
InheritCurrentSource(provider);
InheritParameters(provider);
return provider;
}
protected override void Dispose(bool disposing)
{
_viewModel = null;
base.Dispose(disposing);
}
}
My view model looks like this:
public class SchematicViewModel
{
private readonly string _imageName;
public SchematicViewModel(string imageName)
{
_imageName = imageName;
}
public string GetMediaFileName()
{
return _imageName;
}
}
And the code behind looks like this:
public MainWindow()
{
InitializeComponent();
RadMap1.SpatialReference = new EPSG900913Projection();
RadMap1.Provider = new SchematicProvider(new SchematicViewModel("C:\\temp\\image.png"));
// image is 8000 wide by 6000 high and I want to position the map center on the image center
RadMap1.Center = new Location(3000, 4000);
}
If I don't set the GoeBounds in the provider then I can't zoom and pan as expected. If I do set the GeoBounds then when I click the minimap button the app crashes with the following exception:
System.ArgumentException
HResult=0x80070057
Message=Width and Height must be non-negative.
Source=WindowsBase
StackTrace:
at System.Windows.Size..ctor(Double width, Double height)
at Telerik.Windows.Controls.Map.SpatialReference.GetSizeInKilometers(Location basePoint, Size size)
at Telerik.Windows.Controls.Map.LocationRect.CalculateGeographicalSize()
at Telerik.Windows.Controls.Map.TilesVisualizationLayer.CalculateRegion()
at Telerik.Windows.Controls.Map.TilesVisualizationLayer.OnMapChanged(RadMap oldMap, RadMap newMap)
at Telerik.Windows.Controls.Map.InformationLayer.InformationLayerLoaded(Object sender, RoutedEventArgs e)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.BroadcastEventHelper.BroadcastEvent(DependencyObject root, RoutedEvent routedEvent)
at System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(Object root)
at MS.Internal.LoadedOrUnloadedOperation.DoWork()
at System.Windows.Media.MediaContext.FireLoadedPendingCallbacks()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at ProvidersUriImageProvider.App.Main()
What am I doing wrong?
Thanks
Pete