I'm developing a mobile application (xamarin.android & c#). Situation is showing an image having a certain width, e.g. 2380 pixel. I'm using the "ShowPress"-gesture so that the user is able to mark s a point on the picture. Now I need the location on the picture.
The event gets a parameter that provides the values RawX as well as RawY relating to the screen. How can I get the size of the ImageView? I need it to determine the position on original bitmap.
public void OnShowPress(MotionEvent e)
{
var x = e.RawX;
var y = e.RawY;
How can I achieve this?
You could read this document : MotionEvent,
Position e.RawX/e.RawY is related to the screen :
Returns the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views.
Position e.GetX/e.GetY is related to the view :
getX(int) for the first pointer index (may be an arbitrary pointer identifier).
Better understanding :
RawX/RawY that is guaranteed to return absolute coordinates, relative to the device screen.
While GetX()/GetY(), should return you coordinates, relative to the View, that dispatched them.
So you could use e.GetX()/e.GetY() to determine the position on your original bitmap.
Related
I am using Xamarin native (not forms) and I have an ImageView inside a RelativeLayout.
Is there any way to get the absolute position of the view relative to the screen and not relative to the parent?
I saw some solutions for this problem on Xamarin.Forms that loop through the parent view and add its coordinates relative to its parent, but it doesn't seem to work here.
I tried using iv.GetX() but this is for getting the position in relative to the parent.
What is the way to get the absolute position?
Thanks in advance.
You could get the absolute coordinates across the entire screen with the GetLocationOnScreen method.
like:
int[] location = new int[2];
iv.GetLocationOnScreen(location);
int x = location[0];
int y = location[1];
Note:
This value is calculated from the top of the screen, which includes the height of the notification bar.If those parameters are printed in the Activity's OnCreate() method, they are all 0, and you won't get them until the UI controls are loaded.
It's better to get it in OnWindowFocusChanged method.
I'm working on a Winforms app that contains a large map image (5500px by 2500px). I've set it up so the map starts in full size, but the user can zoom out to a few different scales to see more of the map. The user is able to drag the map around to shift what they are looking at (like Google Maps, Bing Maps, Civilization, etc.).
When the map is full sized (scale = 1.0), I am able to prevent the user from scrolling past the borders of the image. I do this by calculating if they are trying to move past 0, or past the image width - current window size, similar to this:
if (_currHScroll <= 0) {
_currHScroll = 0;
}
This all works just fine. But, when I zoom out on the map (thus, making the image smaller), the limits for the bottom and right of the map break down. I know why this happens--because the Transform that is performed basically "compresses" the map a little bit, and so what used to be a 5000 px image is now smaller, depending on the scale. But, my limiters are based on the image size.
So, the user can scroll past the end of the map, and just sees white space. Worse things happen, I realize, but if possible I'd like to keep them from doing that.
I'm sure there is a straight-forward way to do this, but I haven't figured it out yet. I've tried simply multiplying my calculation by the scale, but that didn't seem to work (seems to under-estimate the size initially, then over-estimate on the smallest sizes). I've tried calculating the transform location of the bottom right of the image, and using that, but it turns out, that number is inverted, and I can't find what it relates to.
I'm including my transform point method here. It works just fine. It tells me, regardless of zoom level, what pixel was clicked on the original image. Thus, if someone clicks on point 200, 200 but the image is scaled at .5, it will show something like 400,400 as what was clicked (but, as I said, I don't think the scale value is a multiplier--using this just for demonstration purposes).
public Point GetTransformedPoint(Point mousePoint) {
Matrix clickTransform = _mapTransform.Clone();
Point[] xPoints = { new Point(mousePoint.X, mousePoint.Y) };
clickTransform.Invert();
clickTransform.TransformPoints(xPoints);
Debug.Print("Orig: {0}, {1} -- Trans: {2}, {3}", mousePoint.X, mousePoint.Y, xPoints[0].X, xPoints[0].Y);
return xPoints[0];
}
Many thanks in advance. I'm sure it's something relatively easy that I'm overlooking, but after several hours, I'm just not finding it.
If i understand right, you can calculate the maximum with your method GetTransformedPoint by using width and height from your Image as Point. The result can then be used inside your check...
And by the way, you are right, the scale value is a multiplier used as a factor. The only thing is, you have to cast the result to an integer.
Currently, I'm using a WPF Image control to display images. I want to do the following: On a MouseUp, MouseDown or MouseMove event, I want to get the coordinates of the point under the cursor, not with reference to the top-left corner of the control, but with respect to the actual coordinates of the displayed bitmap, which may have been re-scaled, or may have a different aspect ratio than the control itself. If an alternate control provides this functionality, I'd be equally happy to hear about it. Thanks in advance.
EDIT: I'd also like so may to know it if the coordinates of the control were out of range of the image, due to a different aspect ratio.
you can get the coordinates of the mouse by this way :
private void image1_MouseDown(object sender, MouseButtonEventArgs e)
{
Point point = e.GetPosition(image1); //position relative to the image
Point point2 = e.GetPosition(this); //position relative to the window
}
Hope that answered a part of your question.
You can use the various TransformTo* methods of the Visual class to get, coordnates relative to a sepcific control, it will take all transformation applied to the visual tree into account.
Also, if you attach MouseUp, MouseDown and MouseMove to the Image control itself, you should already get the correct coordinates from the MouseButtonEventArgs and if you use the mouse outside of the visual bounds of the control, you will not get those events, so you don't need extra code check for coordinates being out of bounds.
If your actual goal is to find out which acutal pixel of your bitmap image has been touched by the mouse (as you would need for a bitmap/pixel editing software) things get much harder because WPF uses virtual device indendent pixels that do not directly relate to pixels on the screen or pixels in a bitmap that has been rendered in an Image control. The Image control internally scales a bitmap image based on the DPI settings of the bitmap file itself and based on the DPI settings of operating system.
i am trying to develop a remote desktop apps with c#. so i have couple of question regarding mouse coordinate calculation based on picture box
suppose i have picture box and i want to capture mouse coordinate when i will move my mouse
on that picture box in c#?
if i click at location (200, 300) on my picture box. then how can i determine
programmatically resolution of picture box and convert that (200,300) coordinate based on
that resolution.
when i will send (x, y) coordinate to other machine and if that pc has resolution have like
1024x768 then what logic i need to use to convert (x, y) according to that pc resolution
if possible help me with small sample code for my question. thanks
This sounds like a trivial question, if it's something homework related, add a tag homework.
int remote_x = local_x * remote_width / local_width;
int remote_y = local_y * remote_height / local_height;
The dimensions of the picture box (local_width and local_height) can be determined e.g. by using pictureBox.Width and pictureBox.Height. The cursor coordinates, local_x and local_y can be requested or are part of the event data (e.g. of the MouseMove event).
Simple, the easiest way is to transform your coordinates to a normalized form (ranging from 0 to 1). Then you can use these normalized coordinates to calculate the mousePosition on another resolution. This way the devices don't need to know the other devices resolution.
So:
//First Normalize the clickPosition using the current resolution
//clickPos(200,300) and resolution(800,600) => normalized(0.25,0.5)
var normalized = clickPos/resolution;
//Now you can send this information to the other device
//The other device uses the normalized parameter to calculate the mouseClick with his resolution
//normalized(0.25,0.5) and otherResolution(1280,720) => otherDeviceClickPos(320, 360)
var otherDeviceClickPos = normalized * otherResolution;
If you know the resolution of the remote screen and you know the size of the picture box then it's simply ratios rounded off to an integer.
I have made a program that reads voltage and current values of some diode curves from an xml file and draws them on screen (Just using plain 2D graphics and some simple commands like DrawCurve and stuff like that).
My main image frame is 800 by 800 pixels (you can see a smaller screenshot down below). Now I want to add a zoom function that when I hover the mouse over this image area, a flying smaller square pops up and zooms in + moves when I move the mouse over this area.
I have no idea how to approach this. Ofcourse I don't ask the full working code but please help me to get closer and closer!
For instance, can I make the zoom to work, without reading the curve data and painting real time? or there is no escape from it? How can I have a hovering image box when I move mouse over the orginal image?
Thanks!
Have you timed how long DrawCurve takes? Perhaps it's fast enough to do in real time. Don't forget, the GDI will clip the drawing primitives to the drawing area. You just need to set up a clipping rectangle as you move the mouse around.
To speed up the redraw, create the main window image (the one you pasted) as an off-screen bitmap, and just DrawImage the off-screen version to the window in the paint events. That way you reduce the impact of the DrawCurve.
Finally, to get good looking results, overload the OnPaintBackground (can't remember the name exactly but it's something like that) so it does nothing (not even call the base class) and do all your painting in the OnPaint method using a BufferedGraphics object.
Update
Your paint function might look like this:
OnPaint (...)
{
the_graphics_object.DrawImage (the background image);
the_graphics_object.Clip = new Region (new Rectangle (coords relative to mouse position));
the_graphics_object.TranslateTransform (drawing offset based on mouse position);
RenderScene (the_graphics_object, scale_factor); // draws grid and curve, etc
the_graphics_object.DrawRectangle (zoom view rectangle); // draw a frame around the zoomed view
}
This will produce a floating 'window' relative to the mouse position.
Typically, cases where redrawing can be time consuming, zooming is usually tackled by providing a "quick but ugly" implementation, alongside the "correct but slow" implementation. While the zoom operation is actively in progress (say, while the user has a slider clicked, or until a 50ms since the last change in zoom value has happened), you use the quick and ugly mode, so the user can see a preview of what the final image will be. Once they let go of the zoom slider (or whatever mechanism you provided), you can recalculate the image in detail. The quick version is usually calculated based on the original image that you are working with.
In your case, you could simply take the original image, work out the bounding box of the new, zoomed image, and scale the relevant part of the original image up to the full image size. If say 100ms has passed with no change in zoom, recalculate the entire image.
Examples of this kind of functionality are quite widespread: most fractal generators use exactly this technique, and even unrelated things like Google StreetView (which provides a very ugly distorted version of the previous image when you move around, until the actual image has downloaded).