Lets say I have a map in Mercator projection, and I know top and bottom latitudes:
topLatitude = 80; bottomLatitude = -55;
I also know width and height of a map:
width = 800; height = 500;
I want to rescale the map to Equirectangular projection, keeping the same width.
How can I calculate new height of a map?
I came up with a solution.
This is formula to calculate x and y of Mercator projected map:
Here is function for y:
function degreesToRadians(degrees){
return degrees / 180 * Math.PI;
}
function mercatorLatitudeToY(latitude){
return Math.log(Math.tan(Math.PI / 4 + degreesToRadians(latitude) / 2));
}
When R=1 the result you get is radians. So I calculate y for top and bottom latitudes.
Next, I calculate the same radians if the projection is Equirectangular - I simply need to convert top and bottom latitude to radians. And last thing - I just need to find aspect ratio of differences:
var scale = (mercatorLatitudeToY(topLatitude) - mercatorLatitudeToY(bottomLatitude))/ (degreesToRadians(topLatitude) - degreesToRadians(bottomLatitude));
For map without Antarctica, aspect ratio is ~1.5
Related
Working on a private stock chart where I use a rendering rectangle with an origin at lower left and inverted y axis, scale factor y is negative. Y axis ticks render nicely but drawing text (drawstring) is where I run into problems.
using (Pen pen = new Pen(_color))
using (Font drawFont = new Font("Arial", 16))
using (SolidBrush drawBrush = new SolidBrush(Color.Black))
{
pen.Width = 1F / e.Graphics.DpiX;
foreach (float tick in this.TimeSeriesPanelControl.YTicks)
{
e.Graphics.DrawLine(pen, right, tick, right + 10, tick);
// this is not producing text to the right of the tick that renders properly.
e.Graphics.DrawString(tick.ToString("F2"), drawFont, drawBrush, right + 15, tick);
}
}
I have seen that the text is upside down caused by the negative scale factor on the y coordinate.
The question is how to make drawstring render the text to the right of the tick?
I have two sets of Lat and Long values corresponding to two corners of a rectangle (top left and bottom right). I want to load a image in the rectangle and as the user clicks on the locations on the rectangle/image, it should return a latitude and longitude (from the detected pixel's coordinates). What should be the calculation to convert pixels to lat and long, given the above spot of inputs.
You should know what geodetic projection has been used to create that map and how rectangular coordinates correspond to geographic ones.
For small map pieces you can use linear approximation, so coordinates might be calculated with linear interpolation.
Example for x-coordinate and longitude:
Lon = LonLeft + X * (LonRight - LonLeft) / Width
Assuming linear interpolation is good enough for your purposes, you can use following formula:
out = (in - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
where in* are image coordinates and out* are map coordinates.
You have to use formula twice; once for horizontal and once for vertical coordinate.
Im trying to do a graph from evalued math function and this is last think I need to do. I have graph with limit coordinates -250:-250 left down and 250:250 right up. I have Y-limit function, which is defined as -10:10, but it could be user redefined and if it is redefined, I need to calculate new coordinates.
I have now field of y-coordinates with 20000 values and each of is multiply by:
ratioY = 25 / (fabs( up-limit - down-limit ) / 20) which will make coordinates adapt for new Y-limit (if limit is -5:5, graph looks 2x bigger), this works good, but now isnt graph exactly where it should be (see pictures). Simply 25 is multiplied for postscript coordinates and (up-limit - down-limit) / 20 is ratio for "zooming" Y coordinates. This works fine.
Now Im trying to "move coordinates" which will subtracted from revaluated value:
ycoor = (ycoor * ratioY) - move-coorY ;.
Now I have something like this:
move-coorY = 25* ( ( up-limit - down-limit) /2 );
and it doesnt work correctly. I need to do sin(0) start from 0.
This is a correct graph which is -10:10
(source: matematika.cz)
This is a bad graph which is -5:10
(source: matematika.cz)
Maybe its easier not to do this with fixed numbers (like your ratioY) but with two different coordinate systems. Physical coordinates are in your problem domain, i.e. they are the real values of your sine curves. Logical coordinates refer to the device, in your case they are the point values in Postscript, but they might be pixels on a HTML canvas or whatever.
I'll denote the physical coordinates of the first axis with a small x and the corresponding logical coordinate with a capital X. In each coordinate system we have:
Lower bound: x_min, X_max
Upper bound: x_max, X_max
Range: dx = x_max - x_min
dX = X_max - X_min
Then you can calculate your logical coordinates from the physical ones:
X(x) = X_min + (x - x_min) * dX / dx
This also works vice versa, which is not an issue for Postscript files, but max be useful for an intractive canvas where a mouse click should yield the physical coordinates.
x(X) = x_min + (X - X_min) * dx / dX
In your case, the ratio or scale factor is dX / dx, which you can calculate once for each axis. Let's plot the first point with y == 0 in your first graph:
y_min = -10
y_max = 10
dy = 20
Y_min = -250
Y_max = 250
dX = 500
Y(0) = -250 + (0 - (-10)) * 500 / 20
= -250 + 10 * 500 / 20
= 0
In the second graph, the logical coordinates are the same, but:
y_min = -5
y_max = 10
dy = 15
Y(0) = -250 + (0 - (-5)) * 500 / 15
= -250 + 5 * 500 / 15
= -83.3333
If you change the range of your graph, e.g. from (-10, 10) to (-5, 10), just adjust the physical coordinates. If you resize your graph, change the logical coordinates. (Also, calculating the point in the graph is the same as calculating the position of the tick mark for the axis. Strangely, you got the tick marks right, but not your graph. I think your problem was to account for the non-zero lower bound in both graph and curve data.)
Also, it's probably better to re-evaluate the logical coordinates when printing instead of transfroming them from a previous plot. You can do that on the fly, so that you only need to keep the physical data in an array.
(And lastly, I'll admit that I'm not entirely sure these two kinds of cooirdinates are called physical and logical. I know these terms are used, but it may be the other way round or they might even mean sonething different altogether.)
My friend did a well yob for me and programmed this...
double zeroPosition(double startY, double endY){
double range = endY - startY;
double topSize = endY / range;
return 250.0 - 500 * topSize;
}
This will calculate position of zero, which I just add to my Y position with ratio and It works exactly how I need!
But thanks M Oehm ;)
I want to get Screen Position from World Position in DirectX.
I can get my ball's world position. But I can't know how can I convert it to screen position.
You have a view/eye transform V (the one that "places" your "camera") and a projection transform P.
Clip space coordinates are reached by
clip_position = P * V * world_space_position
From clip space you reach NDC space by dividing the clip space coordinates by the 4th clip space coordinate w, i.e.
ndc_x = clip_x / clip_w
ndc_y = clip_y / clip_w
ndc_z = clip_z / clip_w
ndc_w = clip_w / clip_w = 1
The viewport XY coordinates are then reached by mapping the range [-1,1] to the viewport dimensions. The difference between OpenGL and DirectX is, that in OpenGL the depth range [-1,1] is mapped to [0, DEPTH_BUFFER_RESOLUTION], while in DirectX it's the depth range [0, 1] that maps to the depth buffer value range.
I have a world map that is 800px wide and 340px high. How can I find the position of a city like, for example, New York with latitude 40.75 and longitude -73.98? I would like to pin a marker over this point.
So far I have been adding cities manually which is problematic.
Is there any way to convert latitude and longitude values to x and y coordinates?
Thank you
From this image, you can see the coordinate system for latitude and longitude:
Unless you know the exact location (both pixel-wise and latitude and longitude) of a point on your map, you can't do anything with it. You just won't have enough information.
By x axis and y axis, do you refer to your image? What is the image of (like the whole world, or of a specific region)?
If it's of the whole world, then the coordinates would be:
x = image.width * (longitude + 180) / (2 * 180)
y = image.height * (latitude + 180) / (2 * 180)