I'm facing issue for a class where I need to convert and draw GPS coordinates dynamically into a JPanel. I have this local library data in a file that I parse. The structure is ID, County, Library Name, Latitude, Longitude.
R1,Ramsey,Maplewood,45.0327,-93.0262
R2,Ramsey,Mounds View,45.1059,-93.2104
R3,Ramsey,New Brighton,45.06604,-93.19125
R4,Ramsey,North St. Paul,45.0105,-92.9968
R5,Ramsey,Roseville,45.0072,-93.1558
R6,Ramsey,Shoreview,45.0805,-93.1345
R7,Ramsey,White Bear Lake,45.0831,-93.0092
As you can see, the locations are very close together (7 locations in 170 sq miles, Max Distance apart: 15.5 miles). My code currently can draw and link the nodes properly from hardcoded coordinates instead of the GPS data. I have found algorithms for converting the GPS lat and long to XY coordinates, but once the calculations happen, all the objects print on top of each other since the calculation leads to the same XY because of it being so close. The process needs to be dynamic because I anticipate that the test files to be use will be using 42 locations. What can I do for an equation that will give me XY coordinates that have enough variety to make a decent graphic rendering instead of using random points?
What can I do for an equation that will give me XY coordinates that have enough variety to make a decent graphic rendering instead of using random points?
Find the bounding box. In other words, find the smallest x and smallest y coordinate in your list. Find the largest x and largest y coordinate in your list. Those two points define the bounding box.
Now, translate these location x, y coordinates to drawing x, y coordinates. Your smallest location x, y coordinate becomes drawing coordinate 0, 0. Your largest location x, y coordinate becomes drawing coordinate width, height.
In order to keep the scaling from distorting the image, we have to first calculate the scaling factor for the x coordinate and the y coordinate.
scaling factor x = drawing width / (location maximum x - location minimum x)
scaling factor y = drawing height / (location maximum y - location minimum y)
Then we use the smaller of the two scaling factors.
scaling factor = Math.min(scaling factor x, scaling factor y)
The equations for converting location coordinates to drawing coordinates are:
drawing x = location x * scaling factor
drawing y = location y * scaling factor
Location and scaling factor are doubles, so you don't drop any precision. You have to convert drawing x and drawing y to integers so you can plot them.
Drawing x increases from west to east. Location x probably increases from west to east.
Drawing y increases from north to south. If location y increases from south to north, then you have to take that into account when doing the conversion.
drawing y = drawing height - drawing y
You'll probably will want to add a margin to your drawing area so that none of the locations are drawn on the edge of the drawing area.
Let's say you want a margin of 10 pixels. That would make the actual drawing area 20 pixels larger in width and 20 pixels larger in height.
You then add 10 pixels to the drawing x and the drawing y before you plot your location.
The ideal way to go about this is to find the min-longitude and min-latitude , max-longitude and max-latitude and map them to the [0,0] and [JPanels.width , Jpanels.Height].
this map can be done just
Point map(cure_location){
int X = (curr_location.longitude-min_longitude)*(scalelog);
int Y = (curr_location.latitude-min_latitude)*(scalelon);
return new Point(X,Y);
}
and scalelog and scalelon are
scalelog = (JPanels.width)/(max_longitude-min_longitude)
scalelat = (JPanels.height)/(max_latitude-min_latitude)
Related
I wrote a simple program using OpenGL ES 2.0 and Java for Android.
This program draw a point in a random position on the screen using an ortho projection matrix, view matrix and a model matrix. In the shader I put matrix * position.
All works well, but then I tried, for testing purpose, to calculate the position of the point by myself, so I used multiplyMV and as arguments I put my MVPmatrix (obtained by using multiplyMM before between projection and view and then between the result and the model matrix) and my point (for example 2f, 3.5f, 0f, 1f). The problem is that sometimes the result I get for x and/or y is greater than 1 or smaller than -1, despite the fact that the point is on the screen. But in normalized device coordinates the point must have a range between -1 and 1 in order to be "on screen".
I really don't understand where is my mistake.
The point has to be in normalized device space [-1, 1] (for x, y, z), after the projection matrix is applied.
But note the point may be a Homogeneous coordinate. This means you have to do a Perspective divide first.
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space. The coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates.
Clip space coordinates are Homogeneous coordinates. In clipspace the clipping of the scene is performed. A point is in clip space if the x, y and z components are in the range defined by the inverted w component and the w component of the homogeneous coordinates of the point:
-p.w <= p.x, p.y, p.z <= p.w.
The clip coordinates are transformed to the normalized evice coordiantes by doing the Perspective divide:
ndc.xyz = (p.x/p.w, p.y/p.w, p.z/p.w)
I have a Canvas on which I've drawn a circle / 360 degree arc. I have the arc start drawing from -90 (the top) rather than the right (0) as is default.
I want to place a rectangle at the top of the same canvas and to reduce the sweep of the arc so that the two do not intersect. I've attached an image to illustrate
So what I need to do is work out what angle is represented by half of the rectangle so that I can adjust where to start drawing my arc. The centre of the circle is at the centre of my Canvas:
[canvas.width /2, canvas.height /2]
I've read some resources like this question but they haven't helped to do much more than make me feel like I know nothing. I tried a few failing formulas ending with this
double adjustment = Math.atan2(rectangleY - circleY, rectangleX - circleX) - Math.atan2(rectangleY - circleY, (rectangleX + rectangleWidth) - circleX);
Can somebody tell me what is the right way to calculate this in Java? I'd also like to know how to find where the rectangle intersects if that's possible (I.e. the width of the shaded orange part on the image) although this is of lesser importance to me right now
Let W be the width of the rectangle, R be radius of the circle, and A be the angle you're looking for.
There's a right-angle triangle with angle A at the center, R as the hypotenuse and W/2 as the side opposite angle A, so
W/2R = sin(A)
so
A = Math.asin(0.5*W/R);
Of course you can't use asin(0.5W/R) when W > 2R
EDIT
To answer the second problem (finding the intersection)
Let H be the distance from the center of the circle to the rectangle. When the rectangle is wide enough that the circle intersects the lower side, there's a right angle triangle with A at the center, R as the hypotenuse, and H as the side adjacent to A
H/R = cos(A) and A = Math.acos(H/R). Calculate both angles and use the smaller one.
I would like to know more about the coordinates of a Rectangle,
in particular:
lower left X
lower left Y
upper right X
upper right Y
Every time, I get confused about how to make dimensions based on these coordinates to draw rectangle.
If possible, can I get a graphical representation briefly about these coordinates positions?
Before someone can explain what the lower-left X, lower-left Y, upper-right X and upper-right Y of a rectangle are about, you need to know about the coordinate system: Where is the Origin (x,y) of a PDF page?
The answer to that question contains all the information you need, except for the graphical representation you are asking for. This is a simple representation of the coordinate system:
The origin of the coordinate system is (0, 0). Positive X values are to the right of the origin, positive Y values are above the origin.
I have drawn a Rectangle and indicates where you can find the lower-left corner (with coordinate (llx, lly)) and the upper-right corner (with coordinate (urx, ury)).
The sides of the rectangle are always in parallel with the X and the Y axis, hence you only need two coordinates to define the rectangle.
I'm trying to write a in-app joystick axis calibration tool.
The joystick axis area should be a rectangle, but in the reality it's a non-linear closed curve and I want to increase the accuracy.
The calibration should work this way:
we have a measured value, and this way we get the correct value:
Correct value = [(measured value)/range] * wantedrange
where range is the difference between the maximum and minimum value measured for that axis.
But there is also an offset to move the center point to the right position, how to calculate it?
EDIT: I also made an image: green rectangle is the expected area, red shape is the "real" inaccurate measured area, finally blue is the wanted calibrated area that I shift to (0,0) so that I can use the ratio to convert coordinates to the bigger green rectangle.
EDIT2:
This image explains how calibration can be even more accurate, thanks to zapl answer:
If we find the blue rectangle center, we can divide the rectangle in 4 rectangles and calculate a ratio between that range and the green rectangle's range.
And the code should be something like this:
if(value<axiscenter) correctedvalue = ((value-axismin)/(axiscenter-axismin)) * wantedaxisrange;
else correctedvalue = wantedaxisrange + ((value-offset-axiscenter)/(axismax-axiscenter-axismin)) * wantedaxisrange;
You can get the position of the blue rectangle by instructing the user to move the joystick along the edges so that the values you see are the red curve. You should also instruct user to leave joystick in centered position since you usually need to know the center. Calcuated center is not always the real center position.
For each axis separate those values by the side of the center they are on and find those that are the closest to the center point. That would work with calculated center. Now you have the blue rectangle.
E.g. on X axis you see values ranging from 0-20 and 80-100, center is ~50 > blue rectangle is 20 - 80.
Assuming you want to calibrate it so that values are 0-100 (green) you calculate correction for the x axis as
calibratedX = (uncalibrated - 20) * 100 / 60
Values are shifted by 20 to the right (-20 to normalize them to 0-60) and their range is 60 (80 - 20) which you want to upscale to 0-100. After that clip values to 0-100 since they will be outside for every point on the red line that was outside the blue rectangle.
Result looks like
where pink are the values after transformation, and the pink area outside the green rectangle is cut away.
Regarding the center point: just run it through those calculations as well.
I'm developing a tube shooter-esque game in java that simulates 3D without actually using any 3D libraries. Right now I have a player-controlled ship that rotates around the center point of the screen, using (in this case, for moving right).
angle += 0.1;
x = Math.cos(angle) * radius + cX;
y = Math.sin(angle) * radius + cY;
Where angle is the placement in relation to the center point (ex. 270 is directly under the center), x and y are the current ship position, radius is the distance from the center, and cX and cY are the center point's location.
Right now revolving around the point works smoothly, but I'm not sure how to handle rotating the actual ship to always point towards the center. I've looked around a lot online but can't figure out how an individual Image (or if that doesn't work, an array of drawLines) can be rotated without affecting other objects on the screen.
Long story short, how would one go about rotating an individual Image to constantly point towards a remote x,y location?
What you need is the AffineTransform class which is basically a matrix class in java. Graphics2D has a draw image variant which accepts an AffineTransform instance:
boolean java.awt.Graphics2D.drawImage(Image img, AffineTransform xform, ImageObserver obs)
To create a transform, you can use 2D matrix operations:
AffineTransform trans = new AffineTransform();
trans.translate(x, y);
trans.rotate(theta);
trans.scale(scalex, scaley);
etc...
Mind that the order is important, probably you will want to scale first, rotate and then traslate the image to the corresponding location. It should do fine.
Java has uses some 3D power to draw as fast as it can, it is faster than a software renderer, but quite far from native opengl.