Value does not fall within the expected range GeoboundingBox WinRT - c#

im trying to fit 2 pois on a bing map for WinRT Universal APP, commonly user position and any other point, so the user can see the map between two points, i have this code:
private void centerMap(Geoposition pos, MapPoi pos2)
{
try {
#if WINDOWS_APP
//TODO PC Maps
#elif WINDOWS_PHONE_APP
GeoboundingBox geoboundingBox = new Windows.Devices.Geolocation.GeoboundingBox(
new BasicGeoposition() { Latitude = pos.Coordinate.Latitude, Longitude = pos.Coordinate.Longitude },
new BasicGeoposition() { Latitude = pos2.lat, Longitude = pos2.lng });
map1._map.TrySetViewBoundsAsync(geoboundingBox,null,MapAnimationKind.Linear);
#endif
}catch(Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
So one more time i have a problem i cannot solve myself.
First i need to understand something that i must be doing bad, im getting System.ArgumentException on the GeoboundingBox constructor, here stack trace:
A first chance exception of type 'System.ArgumentException' occurred in EspartAPP.WindowsPhone.exe
System.ArgumentException: Value does not fall within the expected range.
at Windows.Devices.Geolocation.GeoboundingBox..ctor(BasicGeoposition northwestCorner, BasicGeoposition southeastCorner)
at EspartAPP.Modulos.Modulo_Mapa.centerMap(Geoposition pos, MapPoi pos2)
Here are the coordinates used for the test:
pos var: Lat 40.4564664510315 lng -3.65939843190291
pos2 var: Lat 40.4579103 lngs -3.6532357
Both coordinates are correct, one is the user position just got from gps, the other is a close location.
I cant understand what can be going bad, there must be something that i need to know.
The code i posted just throw that exception, but, if i just do +1 to the pos latitude it works, and seems to be doing it right.
If i add pos2 first (as northwestCorner) it doesnt throw exception, it zooms out to max so i can almost see the entire map (which is obviously wrong)
There must be some rules im ignoring, maybe i have to calc which coordinate should be on northwest position?
EDIT: Was exactly that, working code:
private void centerMap(Geoposition pos, MapPoi pos2)
{
try {
BasicGeoposition nw = new BasicGeoposition();
nw.Latitude = Math.Max(pos.Coordinate.Latitude, pos2.lat);
nw.Longitude = Math.Min(pos.Coordinate.Longitude, pos2.lng);
BasicGeoposition se = new BasicGeoposition();
se.Latitude = Math.Min(pos.Coordinate.Latitude, pos2.lat);
se.Longitude = Math.Max(pos.Coordinate.Longitude, pos2.lng);
#if WINDOWS_APP
//TODO PC Maps
#elif WINDOWS_PHONE_APP
GeoboundingBox geoboundingBox = new Windows.Devices.Geolocation.GeoboundingBox(nw,se);
map1._map.TrySetViewBoundsAsync(geoboundingBox,null,MapAnimationKind.Bow);
#endif
}catch(Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
Sorry for my bad english and problems with this bing maps, this is really poor documented i expect because its the newer API and its a mess to find what you need for the API you are working for.
Thanks in advance.

You are not providing the correct coordinates. As you can read here the first coordinate must be upper left corner of the region (the north west coordinate), the second must be the lower right corner (the south east coordinate). Your pos is the lower left corner and pos2 is the upper right corner.
You get the right coordinates like this:
var nw = new BasicGeoposition();
nw.Latitude = Max(pos.Coordinate.Latitude, pos2.lat);
nw.Longitude = Min(pos.Coordinate.Longitude, pos2.lng);
var se = new BasicGeoposition();
se.Latitude = Min(pos.Coordinate.Latitude, pos2.lat);
se.Longitude = Max(pos.Coordinate.Longitude, pos2.lng);

Related

SkiaSharp Touch Bitmap Image

In the app I'm trying to develop a key part is getting the position of where the user has touched. First I thought of using a tap gesture recognizer but after a quick google search I learned that was useless (See here for an example).
Then I believe I discovered SkiaSharp and after learning how to use it, at least somewhat, I'm still not sure how I get the proper coordinates of a touch. Here are sections of the code in my project that are relevant to the problem.
Canvas Touch Function
private void canvasView_Touch(object sender, SKTouchEventArgs e)
{
// Only carry on with this function if the image is already on screen.
if(m_isImageDisplayed)
{
// Use switch to get what type of action occurred.
switch (e.ActionType)
{
case SKTouchAction.Pressed:
TouchImage(e.Location);
// Update simply tries to draw a small square using double for loops.
m_editedBm = Update(sender);
// Refresh screen.
(sender as SKCanvasView).InvalidateSurface();
break;
default:
break;
}
}
}
Touch Image
private void TouchImage(SKPoint point)
{
// Is the point in range of the canvas?
if(point.X >= m_x && point.X <= (m_editedCanvasSize.Width + m_x) &&
point.Y >= m_y && point.Y <= (m_editedCanvasSize.Height + m_y))
{
// Save the point for later and set the boolean to true so the algorithm can begin.
m_clickPoint = point;
m_updateAlgorithm = true;
}
}
Here I'm just seeing or TRYING to see if the point clicked was in range of the image and I made a different SkSize variable to help. Ignore the boolean, not that important.
Update function (function that attempts to draw ON the point pressed so it's the most important)
public SKBitmap Update(object sender)
{
// Create the default test color to replace current pixel colors in the bitmap.
SKColor color = new SKColor(255, 255, 255);
// Create a new surface with the current bitmap.
using (var surface = new SKCanvas(m_editedBm))
{
/* According to this: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/paths/finger-paint ,
the points I have to start are in Xamarin forms coordinates, but I need to translate them to SkiaSharp coordinates which are in
pixels. */
Point pt = new Point((double)m_touchPoint.X, (double)m_touchPoint.Y);
SKPoint newPoint = ConvertToPixel(pt);
// Loop over the touch point start, then go to a certain value (like x + 100) just to get a "block" that's been altered for pixels.
for (int x = (int)newPoint.X; x < (int)newPoint.X + 200.0f; ++x)
{
for (int y = (int)newPoint.Y; y < (int)newPoint.Y + 200.0f; ++y)
{
// According to the x and y, change the color.
m_editedBm.SetPixel(x, y, color);
}
}
return m_editedBm;
}
}
Here I'm THINKING that it'll start, you know, at the coordinate I pressed (and these coordinates have been confirmed to be within the range of the image thanks to the function "TouchImage". And when it does get the correct coordinates (or at least it SHOULD of done that) the square will be drawn one "line" at a time. I have a game programming background so this kind of sounds simple but I can't believe I didn't get this right the first time.
Also I have another function, it MIGHT prove worthwhile because the original image is rotated and then put on screen. Why? Well by default the image, after taking the picture, and then displayed, is rotated to the left. I had no idea why but I corrected it with the following function:
// Just rotate the image because for some reason it's titled 90 degrees to the left.
public static SKBitmap Rotate()
{
using (var bitmap = m_bm)
{
// The new ones width IS the old ones height.
var rotated = new SKBitmap(bitmap.Height, bitmap.Width);
using (var surface = new SKCanvas(rotated))
{
surface.Translate(rotated.Width, 0.0f);
surface.RotateDegrees(90);
surface.DrawBitmap(bitmap, 0, 0);
}
return rotated;
}
}
I'll keep reading and looking up stuff on what I'm doing wrong, but if any help is given I'm grateful.

Draw point where mouse clicked

I'm using HelixToolkit to see and interact with STL files. I need to draw or mark a point clicked by user on the window. I have the coordinates, I know where to draw that point, but I don't know how to draw it, can someone help me? I post some code to explain what I have right now:
private void vierport3d_MouseRightClick(object sender, MouseButtonEventArgs e)
{
Point mousePos = e.GetPosition(viewPort3d);
PointHitTestParameters hitParams = new PointHitTestParameters(mousePos);
VisualTreeHelper.HitTest(viewPort3d, null, ResultCallback, hitParams);
}
public HitTestResultBehavior ResultCallback(HitTestResult result)
{
RayHitTestResult rayResult = result as RayHitTestResult;
if (rayResult != null)
{
RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult;
//HERE I HAVE THE LOCATION TO DRAW
MessageBox.Show(rayMeshResult.PointHit.X + " " + rayMeshResult.PointHit.Y + " " + rayMeshResult.PointHit.Z);
if (rayMeshResult != null)
{
// I THINK I HAVE TO DRAW THE POINT HERE
}
}
return HitTestResultBehavior.Continue;
}
PD: I show the stl on a viewport3d.
We had same scenario in our project and used a sphere to visually indicate the point.
<ht:SphereVisual3D Radius="0.75" Fill="Red" Center="{Binding ContactPoint}" />
ContactPoint is a Point3D type.
This might help, but its probably not the most effecient.
Try the following:
This will create a 3D sphere that can be rendered at the given coordinates.
var sphereSize = 0.025;
/* keep these values low, the higher the values the more detailed the sphere which may impact your rendering perfomance.*/
var phi = 12;
var theta = 12;
MeshBuilder meshBuilder = new MeshBuilder();
Pass in your x,y,z to the first parameter. i.e. the click 3D location.
meshBuilder.AddSphere( new Point3D(x,y,z), sphereSize , theta, phi);
GeometryModel3D sphereModel = new GeometryModel3D(meshBuilder.ToMesh(),MaterialHelper.CreateMaterial(Brushes.Green,null,null,1,0));
Rendering the Point in your viewport
You will need a ModelVisual3D component as a child of the HelixViewport. ( This can be implemented in C# or in XAML) its up to you, ill show both ways.
C# version
NB: You need a reference to the helixviewport if its defined in xaml. Set the x:Name:"" to something appropriate. e.g x:Name="helixViewPort"
ModelVisual3D visualizer = new ModelVisual3D();
visualizer.Content = sphereModel;
helixViewPort.Children.Add(visualizer);
XAML version
I'll assume your xaml code has at least a helix view port so you'll have to add a ModelVisual3D child to the helix viewport if there's none.
<h:HelixViewport3D x:Name="HelixPlotViewPort" >
<h:DefaultLights/>
<ModelVisual3D x:Name="Visualizer">
</ModelVisual3D>
</h:HelixViewport3D>
//Then in C# add the following
Visualizer.Content = sphereModel;
That should do it, hope it helps, do inform us if you find a better solution. :)

How to apply barrel distortion (lens correction) with SharpDX?

i've made a small application to grap screenshots from any windowed game and send it to the iPhone to creat an virtual reality app, like oculus rift (see https://github.com/gagagu/VR-Streamer-Windows-Server for more info).
The images will be captured with SharpDX and everything is working fine.
Now i want to implement such like lens correction (barrel distortion) and i'm looking for the fastest way to realize it. I'm looking many internet sites with informations about barrel distortion and i think the fastest way is to use a shader for it, but i'm very new to sharpdx (and no knowledge about shaders) and i don't know how to implement a shader to my code. The most tutorials applys a shader to an object (like a cube) but not to a captured image and so i don't know how to do it.
[STAThread]
public System.Drawing.Bitmap Capture()
{
isInCapture = true;
try
{
// init
bool captureDone = false;
bitmap = new System.Drawing.Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);
// the capture needs some time
for (int i = 0; !captureDone; i++)
{
try
{
//capture
duplicatedOutput.AcquireNextFrame(-1, out duplicateFrameInformation, out screenResource);
// only for wait
if (i > 0)
{
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>())
device.ImmediateContext.CopyResource(screenTexture2D, screenTexture);
mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None);
mapDest = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, captureRect.Width, captureRect.Height),
ImageLockMode.WriteOnly, bitmap.PixelFormat);
sourcePtr = mapSource.DataPointer;
destPtr = mapDest.Scan0;
// set x position offset to rect.x
int rowPitch = mapSource.RowPitch - offsetX;
// set pointer to y position
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch * captureRect.Y);
for (int y = 0; y < captureRect.Height; y++) // needs to speed up!!
{
// set pointer to x position
sourcePtr = IntPtr.Add(sourcePtr, offsetX);
// copy pixel to bmp
Utilities.CopyMemory(destPtr, sourcePtr, pWidth);
// incement pointert to next line
sourcePtr = IntPtr.Add(sourcePtr, rowPitch);
destPtr = IntPtr.Add(destPtr, mapDest.Stride);
}
bitmap.UnlockBits(mapDest);
device.ImmediateContext.UnmapSubresource(screenTexture, 0);
captureDone = true;
}
screenResource.Dispose();
duplicatedOutput.ReleaseFrame();
}
catch//(Exception ex) // catch (SharpDXException e)
{
//if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
//{
// // throw e;
//}
return new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);
}
}
}
catch
{
return new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);
}
isInCapture = false;
return bitmap;
}
It would be really great to get a little start assist from someone who willing to help.
I've found some shaders on inet but it is written for opengl (https://github.com/dghost/glslRiftDistort/tree/master/libovr-0.4.x/glsl110). Can i use the also for directx (sharpdx)?
Thanks forward for any help!
Now I've never used DirectX myself, but I suppose you'll need to use HLSL instead of GLSL (which should be fairly similar though). The idea is that you'll have to load your "screenshot" into a texture buffer, as an input to your fragment shader (pixel shader). Fragment shaders are deceptively easy to understand, it's just a piece of code (written in GLSL or HLSL) looking very much like a subset of C to which a few math functions has been added (vector and matrices manipulation mostly) executed for every single pixel to be rendered.
The code should be fairly simple, you'll take the current pixel position, apply the barrel distortion transformation to it's coordinates, then look up that coordinate in your screenshot texture. The transformation should look something like that :
vec2 uv;
/// Barrel Distortion ///
float d=length(uv);
float z = sqrt(1.0 - d * d);
float r = atan(d, z) / 3.14159;
float phi = atan(uv.y, uv.x);
uv = vec2(r*cos(phi)+.5,r*sin(phi)+.5);
Here's a shadertoy link if you wanna play with it and figure out how it works
I have no idea how HLSL handles texture filtering (which pixel you'll get when using floating point values for coordinates), but I'd put my money on bilinear filtering, which may very well give an unpleasant pixelyness to your output. You'll have to look at better filtering methods once you get the distortion working. Shouldn't be anything too complicated, familiarize yourself with HLSL syntax, find how to load your screenshot into a texture in DirectX and get rolling.
Edit : I said barrel distortion but the code is actually for the fisheye effect. Of course both are pretty much identical, the barrel distortion being only on one axis. I believe what you need is the fisheye effect though, it's what is commonly used for HMDs if I'm not mistaken.

C# Maps - RouteQuery giving a false route

So I have a Bing Map control, a GeoCordWatcher getting gps lat and lon, a timer for position intervals and a RouteQuery maker turning the GPS cords into a path for the map.
The points are correct, +- a couple of meters. The problem is that if I am near an intersection or a side street it when the route query runs it takes me off on a half mile expedition that I never went on.
I have tried using both default accuracy and high accuracy but I get the same results. Actually seems to be worse with high accuracy.
Has anyone else had this issue?
RouteQuery rq = new RouteQuery();
List<GeoCoordinate> cords = new List<GeoCoordinate>();
foreach (classes.PositionObj posObj in waypoints)
{
cords.Add(new GeoCoordinate(Convert.ToDouble(posObj.Lattitude), Convert.ToDouble(posObj.Longitude)));
}
rq.Waypoints = cords;
rq.QueryCompleted += rw_QueryCompleted;
rq.QueryAsync();
void rw_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
{
try {
if (e.Error == null)
{
Route myroute = e.Result;
mapRoute = new MapRoute(myroute);
mapRoute.Color = (Color)Application.Current.Resources["PhoneAccentColor"];
myMap.AddRoute(mapRoute);
}
}
catch (Exception error) { MessageBox.Show(error.Message); MessageBox.Show(error.StackTrace); leaveFeedback(error.StackTrace); }
}
I haven't been able to test it yet but I think that this is the answer I am looking for.
rq.RouteOptimization = RouteOptimization.MinimizeDistance;
This is the documentation I found
http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.maps.services.routeoptimization(v=vs.105).aspx
http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.maps.services.routequery(v=vs.105).aspx
Try the code:
routeQuery.TravelMode = TravelMode.Driving;

Create images using shapes

Im trying to create a drag and drop module which can be used to build an Image.
EX: Using a triangle and rectangles to create a House.
I have created the drag and drop module but I cant make them fix with each other.
It will be a great help if someone can give me an idea or a sample code for this problem.
Please help me in this.
I'll explain the functionality a little bit, but forgive my English if any mistakes since it's not my native language.
The user is given a set of shapes and a question like "CREATE A HOUSE" so he should be able to drag the shapes that is
given and and build the house.
Thanks in Advance.
if you want to snap the house pieces to grid let's say 50 pixels put these equations
inside mouse up event
box.x = Math.floor(mouseX/50)*50;
box.y = Math.floor(mouseY/50)*50;
box.addEventListener(MouseEvent.MOUSE_UP,mUp)
function mUp(e:MouseEvent)
{
box.stopDrag();
box.x = Math.floor(mouseX/50)*50;
box.y = Math.floor(mouseY/50)*50;
}
that will fit the pieces together
Use this as a base class for your drag-able objects:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Dragable extends Sprite
{
// vars
private const SNAP:uint = 40;
/**
* Constructor
*/
public function Dragable()
{
addEventListener(MouseEvent.MOUSE_DOWN, _drag);
addEventListener(MouseEvent.MOUSE_UP, _drop);
}
/**
* MOUSE_DOWN
*/
private function _drag(e:MouseEvent):void
{
startDrag();
}
/**
* MOUSE_UP
*/
private function _drop(e:MouseEvent):void
{
stopDrag();
x = Math.round(x / SNAP) * SNAP;
y = Math.round(y / SNAP) * SNAP;
}
}
}
Modify SNAP to meet your requirements.
For something like this (ignoring the dragging and dropping, which you've got some good examples for here), you set all this up previously.
Say your goal is to build a house. Here, you'd assemble the pieces beforehand and save out the final position and rotation in an xml or something similar. When you drag the pieces in the game, you just need to check if it's close enough to the final position and if it is, just snap it to the final position. You can work in rotation easily enough (though I'd keep the angles to 45 degrees for simplicitly).
As an idea for position:
private var m_finalPos:Point = new Point( 10.0, 10.0 );
private var m_snapDist:Number = 100.0;
private function _onDrop( e:MouseEvent ):void
{
// get the distance squared (quicker, and we don't really care about the distance)
var diffX:Number = this.m_finalPos.x - this.x;
var diffY:Number = this.m_finalPos.y - this.y;
var distSq:Number = ( diffX * diffX ) + ( diffY * diffY );
// if we're close enough, snap to the final position
if( distSq < this.m_snapDist )
{
this.x = this.m_finalPos.x;
this.y = this.m_finalPos.y;
}
}
Lower the snapDist to make it harder.

Categories