Closed peder1896 closed 1 year ago
Is there anything specific you are trying to achieve other than just using Mapsui as a map component in your app?
Thanks for your answer What i am trying to do is integrate mapsui (as a SkiaSharp SKCanvasView shown as ”underlay” ) via BlendMode in an application that controls a marine radar/scanner processes the data and display the echoes via SkiaSharp canvas with some other data (AIS traffic and Weather). I also would like to solve how calculate latitude/longitude pos of AIS boat position to screen position via Mapsui. This is the short version of the project i can describe it in more details if you want (send you some screen dumps). I am also planning on using ENC (S57) marine vector charts in the future (like in SharpMap OgrSample.cs ) Regards
So, you already have an application that is drawing to skcanvasview and now you want to use Mapsui to also draw to that existing view?
yes exactly i can send you the code in OnPaintSurface if you want to?
Is it possibly to do what i want theoretically?
This is not what Mapsui has been designed for. It may not be impossible if you make use of some of the lower levels of code. The best option for you is to investigate this with Mapsuis code included in your project, so you can see Mapsuis internals.
I think the key thing to keep in mind in this situation (see also the related issue #1024) is that the tiles need to be retrieved asynchronously before the layer can be successfully rendered. You can handle the layer's DataChanged event to determine when retrieval of all the tiles has been completed (at that point, the layer will no longer be "Busy") and call the layer's RefreshData method to initiate that retrieval. Here is a very bare-bones example:
public void OSMTest()
{
osmMap = new Map
{
CRS = "EPSG:3857",
Transformation = new MinimalTransformation()
};
vPort = new Viewport
{
Center = new Point(0, 0),
Width = 512,
Height = 400,
Resolution = 78271.51696401953125
};
TileLayer osmLayer = OpenStreetMap.CreateTileLayer();
osmMap.Layers.Add(osmLayer);
osmLayer.DataChanged += (s, e) =>
{
var layer = (TileLayer)s;
if (!layer.Busy)
{
// At this point, all tiles will have been retrieved, and we can render the map
// as a PNG image to a MemoryStream, which can in turn be displayed or saved to a file
var bitmap = new MapRenderer().RenderToBitmapStream(vPort, osmMap.Layers, osmMap.BackColor);
}
};
osmLayer.RefreshData(vPort.Extent, vPort.Resolution, ChangeType.Discrete);
}
Additional code may be needed to handle error conditions or cancellation, but this illustrates the core logic. I am using this basic approach to use Mapsui to generate maps for display in a GtkSharp application, where no MapControl is currently available.
Perhaps you can use the extension method that @inforithmics has written for this purpose. It is in the current master but not in 4.0.0-beta.5.
I used this myself to generate bitmap images in an app recently. I just copied it locally. Also the extension on layer:
Thank You very much zur003 & pauldendulk for your help I read your comments and did as you suggested, it worked fine
This is what i did: In class declaration:
Mapsui.Map map = new Mapsui.Map { CRS = "EPSG:3857", Transformation = new MinimalTransformation() };
static MapControl mapControl = new MapControl();
TileLayer tileLayer;
static public Mapsui.Geometries.Point centerOfRadarLonLat = new Mapsui.Geometries.Point(18.91875, 59.28795);
Mapsui.Geometries.Point sphericalMercatorCoordinate = SphericalMercator.FromLonLat(centerOfRadarLonLat.X, centerOfRadarLonLat.Y)
private SKSurface _surface, chartSurface;
double resMapsui;
In class creation:
chartSurface = SKSurface.Create(new SKImageInfo((int)radarRect.Width, (int)radarRect.Height));
if (Device.RuntimePlatform == Device.iOS)
MapControl.UseGPU = false;
chartType = Preferences.Get("chartchoice", (int)ChartChoice.Openstreetmap);
var attribution = new BruTile.Attribution("© OpenStreetMap contributors", "http://www.openstreetmap.org/copyright");
if (chartType == (int)ChartChoice.Openstreetmap)
tileSource = Maptiles.Openstreetmap.Create();
if (chartType == (int)ChartChoice.Googlemaps)
tileSource = Maptiles.GoogleMaps.Create();
if (chartType == (int)ChartChoice.Lantmateriet)
tileSource = Maptiles.LantMaterietTopo.Create();
if (chartType == (int)ChartChoice.Bingmaps)
tileSource = Maptiles.BingAerial.Create();
tileLayer = new TileLayer(tileSource);
map.Layers.Add(tileLayerStreet);
mapControl.Map = map;
vPort = new Viewport
{
Center = sphericalMercatorCoordinate,
Width = 1024,
Height = 1024,
Resolution =2
};
tileLayer.DataChanged += (s, e) =>
{
var layer = (TileLayer)s;
if (!layer.Busy)
{
mapControl.Renderer.Render(chartSurface.Canvas, vPort, map.Layers, map.Widgets, col);
}
};
tileLayerStreet.RefreshData(vPort.Extent, vPort.Resolution, ChangeType.Discrete);
and finally
OnPaintSurface(object sender, SKPaintGLSurfaceEventArgs e)
{
SKCanvas canvas = e.Surface.Canvas;
var surfaceSize = e.BackendRenderTarget.Size;
widthLoc = surfaceSize.Width;
heightLoc = surfaceSize.Height;
_surface = SKSurface.Create(sKImageInfo);
_surface.Canvas.Clear(SKColors.Black);
if (saveRange != Range)
{
resMapsui = (Range / 512)*2;
vPort = new Viewport
{
Center = sphericalMercatorCoordinate,
Width = 1024,
Height = 1024,
Resolution = resMapsui
};
tileLayerStreet.RefreshData(vPort.Extent, vPort.Resolution, ChangeType.Discrete);
saveRange = Range;
_surface.Canvas.DrawSurface(chartSurface, new SKPoint(radarsurftotOffx, radarsurftotOffy));
}
if (showChart)
_surface.Canvas.DrawSurface(chartSurface, new SKPoint(radarsurftotOffx, radarsurftotOffy));
if (showChart)
{
using (var paintBlend = new SKPaint())
{
paintBlend.BlendMode = SKBlendMode.Multiply;
_surface.Canvas.DrawSurface(radarSurf, new SKPoint(radarsurftotOffx, radarsurftotOffy), paintBlend);
}
}
canvas.DrawSurface(_surface, new SKPoint(0f, 0f));
}
That's it, see the screen dump for result
Thanks for the feedback. Nice to see what interesting things people are creating with Mapsui 😁.
If you only use the openstreetmap layer it may also be an option to use just BruTile without Mapsui. You need to do a bit more but you will have more control. The samples in the BruTile repository can help you to understand how to do it.
I have a Xamarin.Forms app in where i want to create a map in codebehind and render it in a SKCanvasView and a MapView I have asked this question before and did not have time to look into the problem but now I am having a second try. But still the originsl problem i can not get the map show in canvas if i have not assigned the the map to the mapview ( mapView.Map = map;). The widgets are shown but not the map layers? What am I doing wrong same problem on Android and iOS.
I declare a
in xaml
In codebehind the code is a follows:
I trigger the paint with a button: