Display scale line - ArcGIS Runtime SDK - Xamarin.Forms - c#

I am using the 1st release of the ArcGIS Runtime SDK for .Net - Xamarin.Forms (nuget package here).
One of my requirements is to display a basic scale line on the map. I haven't found any build-in feature for the moment.
It seems to be tricky because each device has different size, different resolution... Any idea on how to implement this ?

OK after few hours, I found that the MapView component has a property UnitsPerPixel that do exactly what I needed:
I've added a small grid (to represent the scale) with a fix width:
<Grid HeightRequest="10" WidthRequest="114" x:Name="Legend">
...
</Grid>
Then when the view point changes, I compute the distance representing by this grid:
MapView.ViewpointChanged += (sender, args) =>
{
ScaleVal.Text = $"{Math.Round(Legend.Width * MapView.UnitsPerPixel, 0)}m";
};
Complete solution here.

Related

UWP: Create shadow in XAML [duplicate]

This question already has an answer here:
Drop Shadow effect in Universal Windows Application
(1 answer)
Closed 5 years ago.
I am currently trying to create a circular button with two ellipse-elements in UWP and want one of them to throw a shadow at a certain angle. I found a way to do so in WPF which looks like this:
WPF XAML:
<Ellipse>
<Ellipse.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="-50" ShadowDepth="50" Softness=".7"/>
</Ellipse.BitmapEffect>
</Ellipse>
What's the equivalent in UWP?
The easiest way is to use the DropShadowPanel from UWP Community Toolkit.
So first just install
Install-Package Microsoft.Toolkit.Uwp.UI.Controls -Version 2.0.0
Then use the following code in your XAML
<controls:DropShadowPanel Color="Black"
OffsetX="-50"
OffsetY="-50"
BlurRadius="50"
ShadowOpacity=".7"
Width="120"
Height="120"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<Ellipse />
</controls:DropShadowPanel>
In UWP there is a different component to do this job. It's called the Composition API and is available in the NuGet Package "Win2D.uwp".
Basically you'll need to get the compositor for your visual object with
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
and create a drop shadow using the compositor.
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
// create a red sprite visual
var myVisual = _compositor.CreateSpriteVisual();
myVisual.Brush = _compositor.CreateColorBrush(Colors.Red);
myVisual.Size = new System.Numerics.Vector2(100, 100);
// create a blue drop shadow
var shadow = _compositor.CreateDropShadow();
shadow.Offset = new System.Numerics.Vector3(30, 30, 0);
shadow.Color = Colors.Blue;
myVisual.Shadow = shadow;
// render on page
ElementCompositionPreview.SetElementChildVisual(this, myVisual);
The downside beeing, that this is not quite straight forward. You can use different brushes to display images, solid colors or other stuff, it won't apply to existing visuals on screen (as far as I understand it). You can read more about the basics here. Probalby you'll need to use a surface brush, which can hold a wide variety of different visual types, like images. Currently it does not look like there is a ready made component for ellipses though.
Alternatively there exists a xaml extension which will do all that stuff for you using pure xaml, might be worth a shot and maybe also support ellipses.
As an ending note, all of this is currently a work in progress on microsofts part and should become a native part of the UWP API in the future.

Display compass - ArcGIS Runtime SDK - Xamarin.Forms

I am using the 1st release of the ArcGIS Runtime SDK for .Net - Xamarin.Forms (nuget package here).
One of the requirements is to display a compass that indicates the north. I haven't found any build-in feature for the moment. Is someone can point me out how to implement this functionality ?
So after few research, I've implemented a custom solution:
Find a compass icon that can rotate (see this article to add image resource to Xamarin.Form)
Add the image on top of the map:
<Image x:Name="NorthArrow" />
Rotate the image when the view point changed:
MapView.ViewpointChanged += (sender, args) =>
{
NorthArrow.Rotation = -MapView.MapRotation;
};
Complete solution here.

How to get a ScrollViewer to zoom in to see individual pixels?

I'm making an app for Windows 8.1 where it is important to be able to zoom in and examine images in detail. If I just open up the bitmap and zoom in it looks like.
However when I load the image into my app and use the ScrollViewer to zoom in I get.
As it appears to be trying to interpolate pixel values for some sort of anti-aliasing.
How can I get it so that when I zoom in it shows (as best it can) the exact pixels of the image? In particular I'm using the image as the background to a canvas which is contained in a scroll viewer.
I've looked around on here and MSDN and found a pair of related questions, but as yet they don't seem to have solved my exact problem.
A discussion on WPF
A similar issue with a canvas
Older related question on pixel art
A way to use bitmap encoding (which I couldn't get to work)
Similarly phrased question
There is no easy way to go about this, your best option is to use DirectX to render the image much larger so that you can mitigate the effect of WinRT automatically interpolating pixel values.
As someone explained on MSDN and based on this outstanding request I can't see any other way to accomplish this.
Use Win2D
Win2D is a DirectX inter-op library for WinRT. With this you can render the image at a much larger size, and then set the default zoom level for the scrollViewier to be very small. Because of this when you zoom in it will appear to be that you can see the individual pixels without any fuzzy/blurry interpolation because you will actually be seeing groups of 64 pixels or so all as one color. I couldn't find any way to actually override what kind of interpolation gets done so this seems to be the best method.
Download Win2D as a NuGet package using Visual Studio, Win2D's
quickstart guide does a good job explaining some of the setup
Set up your canvas and the draw event and use the DrawImage function to render the image larger
<ScrollViewer x:Name="Scroller" ZoomMode="Enabled"
MinZoomFactor="0.1" MaxZoomFactor="20">
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" CreateResources="create"/>
</ScrollViewer>
In the canvas_draw function.
canvas.Width = original.Width * 10;
canvas.Height = original.Height * 10;
args.DrawingSession.DrawImage(bitmap,new Rect(0,0,original.Width*10,original.Height*10), new Rect(0,0,original.Width,original.Height), 1.0f, CanvasImageInterpolation.NearestNeighbor);
Make sure to set your canvas to be larger as well
In your code behind set the default zoom of your ScrollVieiwer to be appropriate so your image appears to be the same size.
In the page constructor
Scroller.ZoomToFactor (0.1f);
Other Ways Which I Looked Into and Didn't Work
Making the canvas very large and using BitmapEncoder/BitmapDecoder with the interpolation mode set to NearestNeighbor, this introduced lots of visual artifacts even when scaled to a power of 2 size
Render options only appear to be usable in WPF and not WinRT
It may also be possible to use some image manipulation library to simply make the bitmap 10x or so as large and then use that, but I ended up using Win2D instead.

Splashscreen Rect coordinates returning Screen dimensions on Win 10 Mobile

I am trying to create an extended SplashScreen on my UWP app for which the SplashScreen image coordinates are needed. I am using the following code in App.xaml.cs:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
if (e.SplashScreen != null)
var SplashLocation = e.SplashScreen.ImageLocation;
//Rest of initialization...
}
However, if I inspect SplashLocation which is a Rect, SplashLocation.Height and SplashLocation.Width return 1280 and 768 which is the dimension of my phone's screen. All other properties are 0.
Is this a known bug in Win 10 Mobile [build 10536]? It works fine on desktop Windows 10.
Actually the issue is that the code given on the MSDN docs is wrong. Have a look at their samples on Github instead. You can find it here:
Splash Screen Sample
Notice the differences between the MSDN docs and the sample:
ExtendedSplash DOES NOT extend page
They use a ScaleFactor for phone
The root element of the XAML is Grid and not page.
I followed their sample (after hours of wondering) and it all worked well. I hope they update their docs to reflect the correct thing.
As a workaround, here's what I did:
Create an Image in XAML inside a Grid (and NOT inside a Canvas as suggested by the msdn Docs)
<Image Name="ExtSplash"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="Assets/Splash/SplashScreen.png"/>
Now, the trick is to make it work on both Mobile (which doesn't give correct Rect coordinates and Desktop (which works as expected)
So, in the loaded event of Page in code behind, I used this code:
if (splash.Top < splash.Left)
ExtSplash.Margin = new Thickness(splash.Top);
else
ExtSplash.Margin = new Thickness(splash.Left);
where Splash = e.SplashScreen.ImageLocation from the OnLaunched event in App.xaml.cs.
This works because, Splash.Top and Splash.Left both return 0 in case of Mobile. So the app just displays the splashscreen fully extended to the width. In case of Desktop, the Image may have some Left or Top Coordinates as it's reported correctly on desktop, where I set them as Margin for the centrally aligned uniform stretched image.
NOTE 1: There may be cases where a slight variation may occur between splashscreen and the ExtendedSplash image. But in my testing it worked fine. It will continue to work even when in a later build MS fixes the issue, so you can take your time to implement the standard method then.
NOTE 2: I had some issues with this logic if scale-400 splashscreen image was provided. For some reason WM10 picks up the highest resolution available. So I just supplied 100, 125, 150 and 200 scale images (skipped the 400)
I ended up ditching the SplashScreen.ImageLocation approach. The Microsoft tutorial does not work on mobile at the time of writing, and the sample is hackish. Instead I used a simple layout like this for the extended splash screen:
<Grid>
<Image x:Name="splashScreenImage" Source="Assets/SplashScreen.png" MaxWidth="620" MaxHeight="300"/>
<!-- plus some other control -->
</Grid>
The magic is to use MaxWidth/MaxHeight.
On mobile the the image will be slightly different positioned vertically (because of status bar and navigation bar I guess), but otherwise correct including size. On desktop the image seems to be exactly positioned and sized as the initial splash.

Translucency issue using SharpDX on WinRT

I'm having a translucency issue using sharpdx for winrt.
First of all, my code:
On the Mainpage.xaml, I've add a swapchainPanel like this:
<Grid>
<SwapChainPanel x:Name="Panel" />
</Grid>
// There is nothing else...
I've used the same class as the sample from github, for the 3D models rendering:
// Initialisation part
graphicsDeviceManager = new GraphicsDeviceManager(this);
graphicsDeviceManager.PreferredGraphicsProfile = new FeatureLevel[] { FeatureLevel.Level_11_0, };
graphicsDeviceManager.DepthBufferShaderResource = true;
Still in the same class, when loading contents:
models = new List<Model>();
foreach (var modelName in new[] {"dude"})
{
model = Content.Load<Model>(modelName);
BasicEffect.EnableDefaultLighting(model, true);
models.Add(model);
}
model = models[0];
// Instantiate a SpriteBatch
spriteBatch = ToDisposeContent(new SpriteBatch(GraphicsDevice));
base.LoadContent();
And finally, the draw part:
// Clears the screen with the Color.CornflowerBlue
GraphicsDevice.Clear(Color.CornflowerBlue);
model.Draw(GraphicsDevice, world, view, projection);
base.Draw(gameTime);
Everything render fine, but this is what I got for a textured model (It's a bit tricky to notice the translucency on a screenshot...)
Here is what I have with a non-textured model...
I think it comes from rendering in Alpha mode. I've tried to set the BlendState but I get some Exceptions since I'm not using the right parameters.
Ok after some several gradual checks as suggested by #xoofx (thanks :) )
I found that there are some issues using SharpDx.
The ModelRendering sample come with .dae models. When I launch this sample, Everything workes fine and there is no issue.
When I load my model, exported on .dae, .fbx and .obj, transluncency appears with .dae, .fbx, but the toolkit compiler can't compile .obj files that have .mtl associated since some primitives and files tag aren't in the correct format. (even if I check the XNA compatibility in Blender when Exporting)
So what have I done to solve my problem ?
1 - Decrease or make sure my graphic profil is the right profil since I'm on a Intel graphic 4000 that doesn't support directX 11.1 yet...
graphicsDeviceManager.PreferredGraphicsProfile = new FeatureLevel[] { FeatureLevel.Level_11_0, };
2 - Delete everything that the toolkit compiler generated in the Debug directory. I think the compiler doesn't generate twice a file when it already exists/compiled.
3 - Finally, I've noticed that all the part in white/transparent on the pictures in my question are all textured. That kind of color comes from this combination:
I've apply a texture on a model or model part.
Unfortunatly, the Toolkit compiler can't find the texture or the texture value is void.
But when you apply a Texture on a model, surface Specular highlight will be activated, especially the MaterialSpecular (that you can see on a model's part property in VisualStudio. MaterialSpecular takes 4 values : R, G, B and A for Alpha always set the Alpha to 1. My aplha was 0 sometimes :( ).
So the light is freakily reflected and tadaaa we got a beautiful translucent model :)
Also, I Export my model into .fbx and make sure to display the default gray plain color on part that are not textured.
4 - Last but not least, Enable default lightning on the Model.
BasicEffect.EnableDefaultLighting(model, true);

Categories

Resources