Geographic coordinates to screen coordinates algorithm - android

I'm developing a cross platform mobile application that stores positions as geographic coordinates into a db, each of these points represent the top left corner of a graphical object.
This application contains a map control (radmap from telerik), that supports geographic coordinates, so, you just add the rectangle and it draws it correctly.
Due to licensing problem I cannot use the map control in the android version (google doesn't let us use the map control for business applications - https://developers.google.com/maps/faq#tos_commercial, for ios I still didn't check this out), so I will use an image to be used as background.
I've got the top left corner and bottom right geographic coordinates of the "map/image" and I've got to draw the graphical objects inside the area defined by the corners.
Could anyone help me to discover how to convert the geographic coordinates to screen coordinates.
Data example (X,Y):
GEO
Top left corner:
-0,00939846 -0,00504255
Bottom right corner:
0,009398461 -0,01281023
Points to draw:
-0.00464558,-0.00799298
-0.0046509,-0.00845432
-0.00386774,-0.00860988
-0.00344932,-0.00860452
SCREEN
Top left corner:
0 0
Bottom right corner:
? ?
Points to draw
? ?
Screen size
1024 * 768
Thanks for the help,
Luis Pinho

I'm most fluent in iOS so that's what my answers in. I tried to make as many variables as possible so that you could either manually/programmatically override them without changing too much of the other code.
- (CGPoint)convertGeoPoint:(CGPoint)point toView:(UIView*)view {
CGPoint geoTopLeft = CGPointMake(-0.00939846, -0.00504255);
CGPoint geoBottomRight = CGPointMake(0.009398461, -0.01281023);
CGFloat geoWidth = geoBottomRight.x - geoTopLeft.x;
CGFloat geoHeight = geoBottomRight.y - geoTopLeft.y;
// This is the block you would change to suit your needs
CGPoint viewTopLeft = CGPointMake(view.frame.origin.x, view.frame.origin.y);
CGFloat viewWidth = view.frame.size.width;
CGFloat viewHeight = view.frame.size.height;
return CGPointMake(viewTopLeft.x + (point.x-geoTopLeft.x)*viewWidth/geoWidth, viewTopLeft.y + (point.y-geoTopLeft.y)*viewHeight/geoHeight);
}
The basic idea is that you need to convert the point into the new coordinate system. To do this, you need to divide by the appropriate geographic dimension and multiply by the appropriate view dimension.

Related

Warp Image area on touch of a point area?

I need a basic idea for how can i warp image on touch of a particular area. Image filters apply warp on whole image but i want to warp single point, like if i want to warp eye of a person then i will touch on that point. So I need a basic idea about this work.
I have tried this one but its also applies filters on whole image.
https://github.com/Jtfinlay/PhotoWarp
App:
https://play.google.com/store/apps/details?id=hu.tonuzaba.android&hl=en
A warp is not just at a "single point" but over some area that you deform in a smooth way.
To achieve this, you need a geometric transform of the coordinates that works in some neighborhood of the touched point. One way to do this is by applying a square grid on the image and moving the grid nodes around the touched points with some law of yours (for instance, apply a displacement vector to all nodes, with a decaying factor such that far away nodes don't move).
Then you need a resampling function that computes the new coordinates of every pixel and copies the color of the source pixel.
For good results, you must actually work in reverse: scan the destination image and for every pixel retrieve the source coordinates and source pixels. Apply bilinear or bicubic resampling to avoid aliasing.
For ease of implementation, the gridding idea should be adapted as well: rather than deforming the destination grid, keep it unchanged and apply the inverse deformation to the source grid.
Last thing: in the grid approach, see the displacements of the grid nodes as two scalar functions DX(i, j) and DY(i, j) that you can handle separately. From the knowledge of the displacements at the nodes, you can estimate the displacement of any pixel by interpolation (bicubic would be appropriate here).
you can use canvas to detect that portion and stop action on that portion in ontouchlistener
code sample
Bitmap pricetagBmp = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.ic_tag_circle_24dp);
// canvas.drawBitmap(pricetagBmp,left + (right - left) / 2, top + (bottom - top) / 2 - (bounds.height() / 2),circlePaint);
float imageStartX = (left + ((right-left)/2)) - (pricetagBmp.getWidth()/2);
float imageStartY = (top + ((bottom - top) / 2)) - (pricetagBmp.getHeight()/2);
canvas.drawBitmap(pricetagBmp, imageStartX, imageStartY,circlePaint);
and in ontouchlistener if that points detected you can perform no action
Note: you can replace drawBitmap with drawRect or something else with invisible color

Calculate angle of touched point and rotate it on a fixed image or canvas or bitmap image in Android

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

provide circular motion for a custom drawing on touch: Android

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!

Touch event for visible part of the Image

I need to apply click/touch events for only visible part of the View. Say for example a image of size 200X200. Apart from center 50X50, remaining part is transparent. I want to get touch events only for that 50X50 visible part Not on remaining transparent part.
In above image (its single image), only inner Diamond has got visible part. Apart from that Diamond is transparent area. So, if I touch Diamond then only I want to do something else ignore.
Edit :
Rachita's link helped me. I gone through that link and got idea how can I implement. But I could not understand some constants like 320, 240 etc while creating Points. In my case, I know the Diamond (in above image) x and y Ponits (hard coded values asctually). So, using those how can I determine, whether I touched inside Diamond or outside?
my Diamond points are as below
pointA = new Point(0, 183);
pointB = new Point(183, 0);
pointC = new Point(366, 183);
pointD = new Point(183, 366);
Edit :
Finally got solution from Luksprog. Its based on checking touched point pixel color. If color is 0 means, you touched transparent layer else you touched some colored part of the image. Simple, but very effective. Have a look at it here.
AFAIK you can not implement this with onclick listener or my any other direct way .You will have to use onTouchListener .
Firstly set your view dynamically at a specific (x,y) position using this How can I dynamically set the position of view in Android?
Calculate the region your diamond will occupy (you should khow the size of image inorder to calculate area of diamond)
3.Trigger a action in onTouchListener only when x, y fall in the required region. Use How to get the Touch position in android?
check this link to calculate if a given point lies in the required square
EDIT
To understand the coordinate system of android refer to this link How do android screen coordinates work?
Display mdisp = getWindowManager().getDefaultDisplay();
int maxX= mdisp.getWidth();
int maxY= mdisp.getHeight();
(x,y) :-
1) (0,0) is top left corner.
2) (maxX,0) is top right corner
3) (0,maxY) is bottom left corner
4) (maxX,maxY) is bottom right corner
here maxX and maxY are screen maximum height and width in pixels, which we have retrieved in above given code.
Remember if you want to support multiple devices with different screen sizes,make sure you use a relative value for x,y ie some ratio of screen height or width ,as different devices have different ppi
Check if touched point lies in the required polygon
I thinks these link might help you determining if the point touched (you can get x,y from onTouch event eg.event.getX()) lies in the required polygon whose points you have mentioned in the question . determine if a given point is inside the polygon and How can I determine whether a 2D Point is within a Polygon?

Best approach to make a background scrolling game?

i want to do a 2D game with backgrounds and sprites (views) moving on the screen.
I want to make a game with a scrolling ground. I mean the user must see a horizon in the top part of the screen filling the 30% of the screen size. The ground must be scrolling and must be the 70% of the screen size. For example, if i put a car on the ground, the car must be driving into a scrolling road and the sky (horizon) must be seen on the screen, in the top of the road, filling the 30% of the screen.
I am searching in google about scrolling games but i can't find the way to achieve this kind of scrolling ground game with horizon.
Any ideas and approaches will be grated, i'm just making a research about how to do this.
Thanks
This kind of effect can be done in various ways, here is one very basic example I can come up with.
First create a background image for your horizon - a blue sky with a sun would be good. Now create some detail images for the background, such as clouds and birds. These can move accross the background image from left to right (and/or vice-versa). In your rendering code you would render the "background" image first, and then the "detail" images. Make sure that your background image covers around 35% of the screen, so that when you render the 70% ground layer there is some overlap - preventing a hole where the two layers meet.
Next create a textured image for the ground. For this I would use a static image that has the correct type of texture for what you are trying to represent (such as dirt). It may also be good to add some basic detail to the top of this image (such as mountains, trees, etc).
This should be rendered after the background layer.
Once you have this layout in place, the next step would be to simulate the depth of your world. For this you would need to create objects (2D images) that would be placed in your "world". Some examples would be trees, rocks, houses, etc.
To define your world you would need to store 2 coordinates for each object - a position on the x-axis as well as a depth value on the z-axis (you could also use a y-axis component to include height, but I will omit that for this example).
You will also need to track your player's position on the same x and z axis. These values will change in realtime as the player moves into the screen - z will change based on speed, and x will change based on steering (for example).
Also define a view distance - the number of units away from the player at which objects will be visible.
Now once you have your world set up this way, the rendering is what will give the illusion of moving into the screen. First render your player object at the bottom of the ground layer. Next, for each world object, calculate it's distance to the player - if it's distance is within the view distance you defined then it should be rendered, otherwise it can be ignored.
Once you find an object that should be rendered, you need to scale it based on it's distance from the player. The formula for this scaling would be something like:
distance_from_player_z = object.z - player.z
scale = ( view_distance - distance_from_player_z ) / view_distance
This will result in a float value between 0.0 and 1.0, which can be used to scale your object's size. Using this, the larger the distance from the player, the smaller the object becomes.
Next you need to calculate the position on the x-axis and y-axis to render your object. This can be achieved with the simple 3D projection formulas:
distance_from_player_x = object.x - player.x
x_render = player.x + ( distance_from_player_x / distance_from_player_z )
y_render = ( distance_from_player_z / view_distance ) * ( height_of_background_img );
This calculates the distance of the object relative to the player on the x-axis only. It then takes this value and "projects" it, based on the distance it is away from the player on the z-axis. The result is that the farther away the object on the z-axis, the closer it is to the player on the x-axis. The y-axis part uses the distance away from the player to place the object "higher" on the background image.
So with all this information, here is a (very basic) example in code (for a single object):
// define the render size of background (resolution specific)
public final static float RENDER_SIZE_Y = 720.0f * 0.7f; // 70% of 720p
// define your view distance (in world units)
public final static float VIEW_DISTANCE = 10.0f;
// calculate the distance between the object and the player (x + z axis)
float distanceX = object.x - player.x;
float distanceZ = object.z - player.z;
// check if object is visible - i.e. within view distance and in front of player
if ( distanceZ > 0 && distanceZ <= VIEW_DISTANCE ) {
// object is in view, render it
float scale = ( VIEW_DISTANCE - distanceZ ) / VIEW_DISTANCE;
float renderSize = ( object.size * scale );
// calculate the projected x,y values to render at
float renderX = player.x + ( distanceX / distanceZ );
float renderY = ( distanceZ / VIEW_DISTANCE ) * RENDER_SIZE_Y;
// now render the object scaled to "renderSize" at (renderX, renderY)
}
Note that if distance is smaller than or equal to zero, it means that the object is behind the player, and also not visible. This is important as distanceZ==0 will cause an error, so be sure to exclude it. You may also need to tweak the renderX value, depending on resolution, but I will leave that up to you.
While this is not at all a complete implementation, it should get you going in the right direction.
I hope this makes sense to you, and if not, feel free to ask :)
Well, you can use libgdx (http://libgdx.badlogicgames.com/).
The superjumper example will put you in the right way :) (https://github.com/libgdx/libgdx/tree/master/demos/superjumper)

Categories

Resources