I'm putting together a demo of indoor positioning technology for an Android device. The problem is that I am getting quadrant 3 positions from the system I'm using, where 0,0 origin is in the upper right. The map is placed in an imageview that has the origin in the upper left (quadrant 4).
Naturally, when I try to put another image on top to move around according to the position I am getting, it is backwards on the X-axis. What is the best way to display the right coordinates? Can I transform the points as I get them, or is there a way to somehow flip the imageview so that the origin is in the upper right?
You will have to transform the coordinates yourself. It is not complex - mapping the values from one to the other, in general. If the image has a width of "Wo" and you have Vo (View Origin) and Mo (Map Origin) then an x coordinate from the Map is Mx and is transformed as Vx = Mx + Wo. (Mx are map x coordinates that have negative values, no greater than Wo and no less than 0). To transform from the view to the map, do the opposite: Mx = Vx - Wo. (The Vx x-coordinates will not have values less than 0, and at its greatest width, it should result in a "0" on the map.)
That is not CPU intensive, so it should be fast.
Related
I am currently using this gitup touchimageview https://github.com/MikeOrtiz/TouchImageView library.... After zoom,based on the zoom percentage I want to map the longpress coordinates to original image coordinates. Any help will be appreciated
Try to get matrix of ImageView:
float[] values = new float[9];
getImageMatrix().getValues(values);
With this array, you have position of top-left corner in terms of image on indexes 2 and 5. For example, when values[2], values[5] is -10,-10 it means, that left top corner of screen is 10,10 pixel of image. So, you can get coordinate of long press:
float imageX = (pressX - values[2])/scale;
float imageY = (pressY - values[5])/scale;
Recently I work with zoomed images, and use this library: https://github.com/chrisbanes/PhotoView
I think its a bit better, it have some predifined touches with image coordinates, and is still improved (last commit ~2 months ago)
Right now I am using this code as custom layout in android studio. But the large problem is that when pinch-to-zoom, it will zoom into the point 0,0 ,instead of zooming into the finger point.
https://gist.github.com/anorth/9845602
EDIT: Forked the original gist and updated it, view it here. It was a little more complex than I thought. The default pivot point for scaling a view is the center of the view. In order to make this work I had to set the view pivot to (0,0) and the adjust the translation for the pivot from the user's gesture.
I noticed in your onScale() override you are calling scaleDetector.getScaleFactor() but you are not calling scaleDetector.getFocusX() and scaleDetector.getFocusy(). These methods tell you what the focal point of the pinch-zoom is. You will have to call these methods and get this focal point (x,y) then do some calculations to figure out the translation required to keep that focal point. You will have to work this into your dx and dy values so that the translation accounts for the focal point.
To calculate the translation, you would take the focal point and multiply the x and y values by the change in scale factor. This tells you how far the point would move given focal point (0,0). So you would subtract x(updated) from x(original) and y(updated) from y(original) to get that move vector. Your translation values are the negated vector values. So:
scale(delta) = scaleDector.getScaleFactor() -- just the change, not the new scale factor
translation x = x(focal) - x(focal) * scale(delta)
translation y = y(focal) - y(focal) * scale(delta)
So obviously you would add these values to your dx and dy values for translation.
Ohh.. damm Math !! once again stuck. It seems to be easy but i think its not that easy,
Problem Statement: I want to rotate the 3 fixed points which lies on a fixed circle.
1.when 1 point is selected remaining 2 points should be static mode and only selected point should move/rotate on circumference of circle.
2.And all 3 points are connected via 3 lines as shown in images..when we select a point and rotate it,connected lines also increase and decrease..
I already tried to solve this problem finding angle at each instant after touch.but its not quite working as per my need..
something like this
I hope the following explanation enable you to put the steps into your coding language.
Presumption is that the vertex to be moved has already selected and so the calculation of (xcnd,ycnd) as defined below is used to set the selected vertex of the triangle.
Let the constraining circle have centre at (cx,cy) and radius r.
Let the coordinates of where the screen is touched be (xtch,ytch)
Let the coordinates of where the screen is touched relative to the centre be (xrel,yrel)
then xrel = xtch - cx and yrel = ytch - cy
Let the coordinates of the point on the constraining circle when the screen is touched at (xtch,ytch) be (xcnd,ycnd).
xcndrel = xcnd - cx, and ycndrel = ycnd - cy give the coordinates on the constraining circle relative to its centre,
Note that
xrel and xcndrel will have the same signs (ie both positive or both negative)
and yrel and ycndrel will also have the same signs.
the function abs(x) = x if x>=0 and -x if x<0 should be available in whatever language you are using
the function sign(x) may or may not be available, sign(x) =1 if x>0 and -1 if x<0 and undefined for x=0
If not available then sign(x)=x/abs(x)
Check if xrel=0
if xrel=0 xcndrel=0, ycndrel=r*sign(yrel)
Otherwise work in first quadrant ie where x>0 and y>0 using abs(xrel) and abs(yrel)
find angle where screen is touched relative to centre of circle using
theta=arctan(abs(yrel)/abs(xrel))
find the coordinates (xcndrel, ycndrel) by using theta in the first quadrant and then placing in the correct quadrant using the signs of xrel and yrel
xcndrel = sign(xrel)*r*COS(theta)
ycndrel = sign(yrel)*r*SIN(theta)
Screen coordinates can now be found
xcnd = xcndrel +cx
ycnd = ycndrel + cy
I have a custom drawn rectangle which i want to move in a circular path based on touch events.
It follows the direction of the touch for clockwise or anticlockwise movement but basically move in circular motion, as if moving on the edge of the circle.
My current thought process is as follows:
Based on the users current and previous x,y i shall find the angle in degrees and then move this rectangle by the same angle by re-drawing in the new position, just making sure that it moves on the edge of a circle.
But this leads to some confusion on the following:
1. how do i decide whether angle movement is clockwise or anti-clockwise.
2. I am not being able to figure out the math for this properly.
Would this be the best approach or is there a better idea for doing this?
Also, if this is the best approach, could someone please tell me the formula for calculating the angle by which i should move it while taking care of the clocking and anticlockwise ?
could someone please help?
please let me know if any more details are required.
Thanks
Steps
Here are a few steps in order to move your rectangle along a circle's rim when the user taps and holds to the side of the circle:
1. Obtain direction desired.
2. Obtain angle from current x and y coordinates.
3. Add direction (+1 if counterclockwise, -1 if clockwise) to angle.
4. Calculate new x and y coordinates.
5. Update/display rectangle.
Details
1. In pseudocode, direction = sign(Rectangle1.x - UsersFingerPosition.x). Here sign is a function returning -1 if the number was negative, 0 if it is 0, and 1 if it is positive. Note that sign(0) will only result when the user is on the exact x and y of your rectangle's location. In that case, the rectangle would not move (which should be good). In Java, the sign function is Math.signum().
2. To obtain the current angle use the following java code:
double angle = Math.toDegrees(Math.atan2(Circle.y-Rectangle1.y, Rectangle1.x-Circle.x));
Note the order of Circle.y-Rectangle.y and Rectangle.x...Circle.x. This is a result of the coordinate (0, 0) being in the top left corner instead of the center of the screen.
3. Simple enough, just add direction to angle. If desired, do something like
angle += direction*2; //So it will move more quickly
4. To get the new x and y coordinates of your rectangle, use the trigonometric functions sine and cosine:
Rectangle1.x = Math.cos(Math.toRadians(angle))*Circle.radius + Circle.x - Rectangle1.width;
Rectangle1.y = Math.sin(Math.toRadians(angle))*Circle.radius + Circle.y - Rectangle1.height;
(where Circle.x and Circle.y are the coordinates of the center of your circle and Circle.radius is naturally it's radius).
5. This one you'll have to take care of (or have already) :)!
Hope this helps you!
Steps
Here are a few steps in order to move your rectangle along a circle's rim:
1. Obtain finger position/Check that it's still dragging the rectangle.
2. Obtain angle from current x and y coordinates.
3. Calculate new x and y coordinates.
4. Update/display rectangle.
Details
1. This one is probably specific to your code, however, make sure that when the user starts dragging the rectangle, you set a variable like rectangleDragging to true. Before you run the next steps (in the code), check that rectangleDragging == true. Set it to false once the user lets go.
2. To obtain the current angle use the following java code:
double angle = Math.toDegrees(Math.atan2(Circle.y-Finger.y, Finger.x-Circle.x));
Note the order of Circle.y-Finger.y and Finger.x...Circle.x. This is a result of the coordinate (0, 0) being in the top left corner instead of the center of the screen.
3. To get the new x and y coordinates of your rectangle, use the trigonometric functions sine and cosine:
Rectangle1.x = Math.cos(Math.toRadians(angle))*Circle.radius + Circle.x - Rectangle1.width;
Rectangle1.y = Math.sin(Math.toRadians(angle))*Circle.radius + Circle.y - Rectangle1.height;
(where Circle.x and Circle.y are the coordinates of the center of your circle and Circle.radius is naturally it's radius). Subtracting the width and height of the rectangle should center it on the circle's border instead of placing the left, upper corner on the circle.
4. This one you'll have to take care of (or have already) :)!
Hope this helps you!
I have a square that rotates to a random angle and then travels in a straight line in the direction it is pointing. It does this by using a variable as its x axis and then calling
Variable++
Each frame.
unfortunatley i cannot work out how to return the exact position of the square because the square can be travelling at any angle and therefore doesn't rigidly follow the world coordinte grid. This means that the x variable is not the shapes x coordinate.
How do i return the shapes exact coordinates and how do i do it in such a way that i can have two squares drawn from the same class behaving differently.
So you've got a measure of distance from where the object started along its internal sideways axis and a measure of the angle between that axis and the horizontal?
If so then the formula you want is simple trigonometry. Assuming the object started at (x, y) and has travelled 'distance' units along an axis at an angle of 'angle' with the horizontal then the current position (x', y') is:
x' = x + distance * cos(angle)
y' = y + distance * sin(angle)
If you have the origin in the lower left of the screen and axes arranged graph paper style with x increasing to the right and y increasing as you go upward, that assumes that the angle is measured anticlockwise and that the object is heading along positive x when angle is zero.
If you'll permit a hand waving explanation, the formula works because one definition of sine and cosine is that they're the (x, y) coordinates of the point on the outside of a unit circle at the angle specified. It also matches with the very first thing most people learn about trigonometry, that sine is 'opposite over hypotenuse', and cosine is 'adjacent over hypotenuse'. In this case your hypotenuse has length 'distance' and and you want to get the 'opposite' and 'adjacent' lengths of a right angled triangle that coincides with the axes.
Assuming Android follows J2SE in this area, the one thing to watch out for is that Math.sin and Math.cos take an angle in radians, whereas OpenGL's rotatef takes an argument in degrees. Math.toDegrees and Math.toRadians can do the conversion for you.
When you made the shape you should have already specified its X & Y coordinates. Im not too sure what you mean when you say you cant find the coordinates?
Also make sure you do fame independent movement; currently you are adding one to your variable on every loop of your program. This means if it runs a 60 Frame Per Second(FPS) it will move 60 units, but if it runs at 30FPS it will move at half the speed