TK Custom Map Polygon Xamarin Forms - xamarin.forms

How can I make my polygon go throughout the street instead of the weird shape in the image below, the data I am passing have the street coordinates. so I don't know why it makes such a strange shape.
How could I fix this?
public async Task DisplayRoute (List<Position> rpositions, Color color)
{
Polygons = new ObservableCollection<TKPolygon>();
var LoopB = new TKPolygon
{
StrokeColor = color,
StrokeWidth = 4f,
Coordinates = rpositions
};
_polygons.Add(firtline);
await Task.Delay(1000);
LoopB.StrokeColor = color;
await Task.Delay(1000);
}
Use this set of coordinates. how could they go through the streets instead of cutting the line through buildings and the sea?
25.848399-80.120878
25.850423-80.120287
25.85412-80.120397
25.85776-80.120689

Related

How do I render a higher quality image via CustomRenderer in iOS with Xamarin Forms?

This is fairly straight forward, but I have some custom ShellRenderers for my App in Xamarin Forms, and I'm having issues with the scaling of images. In particular, Android looks fantastic with the more pixel-dense image (800x200). It looks great on every screen.
The renderer just ensures that the top of the screen is made of the "theme" color, and is presented in the center of the it. It's that simple/straight-forward.
On iOS, it looks awful and blurred. I'm not sure if there's something I need to set or update (or maybe a different graphics stack?) to make it render with higher pixel density... See my attached renderer:
public class CustomShellRenderer : ShellRenderer
{
#region Methods
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
var renderer = base.CreateShellSectionRenderer(shellSection);
if (renderer != null)
{
var navigationBar = (renderer as ShellSectionRenderer).NavigationBar;
if (navigationBar != null)
{
navigationBar.BarTintColor = Colors.LightColor.ToUIColor(); //static colors
navigationBar.TintColor = Colors.LightColor.ToUIColor();
using (var logo = UIImage.FromResource(typeof(Images).Assembly, "Path.To.Logo.png"))
{
var statusFrame = UIApplication.SharedApplication.StatusBarFrame;
var navigationFrame = navigationBar.Frame;
var width = Math.Max(navigationFrame.Width, statusFrame.Width);
var fullArea = new CGRect(0, 0, width, navigationFrame.Height + statusFrame.Height);
UIGraphics.BeginImageContext(fullArea.Size);
var backgroundColor = Colors.PrimaryColor.ToUIColor();
backgroundColor.SetFill();
UIGraphics.RectFill(fullArea);
var logoArea = new CGRect(width * .35, statusFrame.Height, width * .3, navigationFrame.Height);
logo.Draw(logoArea);
var backgroundImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
(renderer as ShellSectionRenderer).NavigationBar.SetBackgroundImage(backgroundImage, UIBarMetrics.Default);
backgroundImage.Dispose();
}
}
}
return renderer;
}
#endregion
}
Any thoughts? Right now, the problem is that when it renders, there is an 800x200 image trying to squeeze into... 140x30 or so space on some emulators...
Thank you!

SkiaSharp drawing image with GPU acceleration

I want to draw something with GPU acceleration in xamarin.forms. (and save the image later). When I call the following method the first time, I get an image and can show it in SKGLView. But when I call the method again, there is nothing (no error, too)
Can somebody give me a hint?
private SKImage CreateSKImage()
{
SKImage sKImage;
var glInterface = GRGlInterface.CreateNativeAngleInterface();
var grContext = GRContext.Create(GRBackend.OpenGL, glInterface);
var surface = SKSurface.Create(grContext, true, new SKImageInfo(500, 500));
var canvas = surface.Canvas;
var paintStroke = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Stroke,
Color = SKColors.Purple,
StrokeWidth = 1
};
canvas.DrawLine(new SKPoint(0, 0), new SKPoint(500, 500), paintStroke);
surface.Canvas.Flush();
sKImage = surface.Snapshot().ToRasterImage();
return sKImage;
}
edit: when I call the method from SKGLView onPaint, then I get something. But when I call the method from anywhere else the glInterface is null ...hmmmm
How to create the OpenGL Interface the right way???

Xamarin Forms - Image To/From IRandomAccessStreamReference

For personal needs, for the Xamarin.Forms.Map control, I need to create a CustomPin extension. UWP part (PCL project)
I create a MapIcon like it:
nativeMap.MapElements.Add(new MapIcon()
{
Title = pin.Name,
Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/Pin/customicon.png")),
Location = new Geopoint(new BasicGeoposition() { Latitude = pin.Position.Latitude, Longitude = pin.Position.Longitude }),
NormalizedAnchorPoint = new Windows.Foundation.Point(0.5, 1.0)
});
However, by this way, I can't set the Image's size.
I then want to use an Image from my PCL part, resize it and convert it into a IRandomAccessStreamReference. To realize it, I need to convert my Image into a stream, but I can't find the way to make it works ><
Example of the function needed:
private IRandomAccessStreamReference ImageToIRandomAccessStreamReference(Image image)
{
//Here I can set the size of my Image
//I convert it into a stream
IRandomAccessStreamReference irasr = RandomAccessStreamReference.CreateFromStream(/* img? */);
//irasr is then created from img
//I return the IRandomAccessStreamReference needed by the MapIcon element
return irasr;
}
Note: The Image paramter img is a Xamarin.Forms.Image
So first, is it possible? If yes, then thank for any help which could help me.. I already search about how to resize the MapIcon and it's not possible directly from the class [MapIcon].(https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.maps.mapicon.aspx)
Thank for help !
You are right. We can't resize the MapIcon directly as it doesn't provide such properties or methods. MapIcon's size is mostly controlled by the size of image which is set by MapIcon.Image property. And we can set this image's size without using Xamarin.Forms.Image.
To set this image's size, we can take advantage of BitmapDecoder class, BitmapEncoder class and BitmapTransform class like following:
private async System.Threading.Tasks.Task<RandomAccessStreamReference> ResizeImage(StorageFile imageFile, uint scaledWidth, uint scaledHeight)
{
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
{
var decoder = await BitmapDecoder.CreateAsync(fileStream);
//create a RandomAccessStream as output stream
var memStream = new InMemoryRandomAccessStream();
//creates a new BitmapEncoder and initializes it using data from an existing BitmapDecoder
BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(memStream, decoder);
//resize the image
encoder.BitmapTransform.ScaledWidth = scaledWidth;
encoder.BitmapTransform.ScaledHeight = scaledHeight;
//commits and flushes all of the image data
await encoder.FlushAsync();
//return the output stream as RandomAccessStreamReference
return RandomAccessStreamReference.CreateFromStream(memStream);
}
}
And then we can use this method to create a resized image stream reference first and then set it as MapIcon's Image like:
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Pin/customicon.png"));
var imageReference = await ResizeImage(file, 64, 64);
nativeMap.MapElements.Add(new MapIcon()
{
Title = pin.Name,
Image = imageReference,
Location = new Geopoint(new BasicGeoposition() { Latitude = pin.Position.Latitude, Longitude = pin.Position.Longitude }),
NormalizedAnchorPoint = new Windows.Foundation.Point(0.5, 1.0)
});

Place a marker by Latitude and Longitude

I have this code that suppose to place the marker by the latlng
public void initialize() {
geocoder = Geocoder.create();
myOptions = MapOptions.create();
myOptions.setZoom(18);
myOptions.setMapTypeId(MapTypeId.HYBRID);
myOptions.setMapMaker(true);
map = GoogleMap.create(
Document.get().getElementById("map_canvas"),myOptions);
GeocoderRequest request = GeocoderRequest.create();
request.setLocation(LatLng.create(lat,lng));
geocoder.geocode(request, new Callback() {
public void handle(JsArray<GeocoderResult> rslts, GeocoderStatus status)
{
if (status == GeocoderStatus.OK) {
location = rslts.get(0);
map.setCenter(location.getGeometry().getLocation());
marker = Marker.create();
marker.setMap(map);
marker.setPosition(location.getGeometry().getLocation());
}
}
});
When I tested with those coordinates (45.48592686713835, -73.49009937672122)
I only get the nearest address which is the icon A. But what I really wanted is the exact location showed with the green arrow.
Am I missing something ?
You will always get the nearest address, if one may be determined, when using the Geocoder to do a reverse geocode (convert LatLng to address). If you want to use the original coordinates, just place the Marker using the original coordinates. If you are going to convert the LatLng to an address or the closest that the Google Geocoder can get to an address, the results will always give you the LatLng of the nearest known street_address, route, airport, transit_station, neighborhood, sublocality, locality, etc.

get boundaries longitude and latitude from current zoom google maps

i need to know long and lat of my four corners of current area
as in this image
i have tried this but with no luck :
map.getBounds();
any help ?
You are half way there. All you need to do is to get the map bounds and then extract (and properly use) the coordinates of the corners.
var bounds = map.getBounds();
var ne = bounds.getNorthEast(); // LatLng of the north-east corner
var sw = bounds.getSouthWest(); // LatLng of the south-west corder
You get north-west and south-east corners from the two above:
var nw = new google.maps.LatLng(ne.lat(), sw.lng());
var se = new google.maps.LatLng(sw.lat(), ne.lng());
Just keep in mind that the map has to be already initialized, otherwise the map bounds are null or undefined.
If you want to be updated about every change of the viewport, use idle event listener:
google.maps.event.addListener(map, 'idle', function(ev){
// update the coordinates here
});
In Android, you can find out corner LatLng (northeast, southwest) by this way,
in the map, every time the camera listen(means gesture detect) they are called,
private var mapView: GoogleMap? = null
............
mapView?.setOnCameraMoveStartedListener { reasonCode ->
if (reasonCode == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE) {
val screenView: LatLngBounds = mapView.getProjection().getVisibleRegion().latLngBounds
var northeast=screenView.northeast
var southwest=screenView.southwest
var center=screenView.center
Log.v("northeast LatLng","-:"+northeast)// LatLng of the north-east Screen
Log.v("southwest LatLng","-:"+southwest)// LatLng of the south-west Screen
Log.v("center LatLng","-:"+center)// LatLng of the center Screen
}
}
**this is mapbox zoom example**
map.on('zoom', (el) => {
map.getBounds();
});

Resources