Calculate (x,y) from (Lat,Lon) in a cropped equirectangular projection - gis

I have a piece of a map in equirectangular projection. I know (lat,lon) in left-top and bottom-right positions. Now I know I can calculate (x,y) like this:
x = ((lon + 180) * (map_width / 360))
y = (((lat * -1) + 90) * (map_height / 180))
However, it seems that this produces wrong coordinates. My guess is that I have to take into account the left-top and bottom-right (lat,lon) for my image.
So I tried this way (where left, top, right, bottom_lon respresent my image boundaries):
x = ((lon + left_lon) * (map_width / (right_lon - left_lon)))
y = (((lat * -1) + top_lat) * (map_height / (top_lat - bottom_lat)))
But I still don't get the right result. What am I doing wrong?

Answering my own question with these two Python functions:
def lon2x(lon, w):
return int(img_w * ((lon - start_lon) / (end_lon - start_lon)))
def lat2y(lat, h):
return int(img_h * ((lat - start_lat) / (end_lat - start_lat)))

In the accepted answer, it is forgotten that subtracting from height. So, it must be like this:
def lon2x(lon, w):
return int(img_w * ((lon - start_lon) / (end_lon - start_lon)))
def lat2y(lat, h):
return int(img_h) - int(img_h * ((lat - start_lat) / (end_lat - start_lat)))
Edit: They are approximate correct results, but for the very accurate results, you should use the projection method whatever used to creating map (like Mercator or Equirectangular).

Related

circle vs circle sweep test that returns touch point

I'm looking for an algorithm that takes two dynamic circles and returns point of contact. For some reason when trying to search for this I can only find resources like: http://ericleong.me/research/circle-circle/ which describe algorithms that return resulting velocities.
You have not defined problem well.
Let circles centers are moving with equations
cx1 = cx1_0 + t * vx1
cx2 = cx2_0 + t * vx2
cy1 = cy1_0 + t * vy1
cy2 = cy2_0 + t * vy2
where cx1_0 is starting X-coordinate of the first circle, vx1 is x-component of its velocity.
Circles touch each other when center-center distance is equal to the sum of radii. We can use squared values:
(cx1 - cx2)^2 + (cy1 - cy2)^2 = (r1 + r2)^2
Substitute expressions above, open parentheses, solve quadratic equation for unknown parameter t. You can get 0, 1 or two solutions (no interaction, one touching, intersection period exists). Then calculate centers coordinates for moment of touch and get touch point for external touching:
x_touch = (cx1 * r1 + cx2 * r2) / (r1 + r2)
similar for y
Note that I emphasize external because internal touching might occur (in that case distance is equal to the difference of radii, but I think such case is not interesting for you)

Make the element appear at the end of the arc

I am trying to make the image appear at the end of the arc much like this:
but it appears in the middle. So no matter if I set the end angle / start angle anything the image should always appear at the end of the arc.
This is the jsfiddle: http://jsfiddle.net/wQXCL/421/
I know I have to use translate so something like:
.attr("transform", function(d) {
var x = 200 * Math.cos(0.25 * Math.PI);
var y = 200 * Math.sin(0.25 * Math.PI);
return "translate(" + x + "," + y + ")";
});
But this formula is not working as well.
Updated fiddle : http://jsfiddle.net/wQXCL/423/
Here is the formula for points on a circle :
x = cx + r * cos(a)
y = cy + r * sin(a)
So in your fiddle (you dont need to add the center here as you're already there, i think D3 makes the arc around the point of translation. So you are at point 200/100 as you translated there previously. So the center you need to add to the formula is 0,0) :
var x = 60* Math.cos(0.25 * Math.PI)
var y = 60* Math.sin(0.25 * Math.PI)
The problem with this is, D3 arc starts at 90 degrees (i.e 3 o'clock). So you have to take that away (Math.PI/2). You also have to take care of the image size :
var x = 60* Math.cos(0.25 * Math.PI - (Math.PI/2)) -8 ; // take away half the width of the image
var y = 60* Math.sin(0.25 * Math.PI - (Math.PI/2)) -8 ;
The value of 60 is the center of the inner and outer radius as you want the image in the center of both :)
Hope that helps

Solving the Points on a Rotated Rectangle

I am working in AS3.
I have a generic rectangle. This rectangle can have any length, any width and any rotation. I am trying to solve for the x and y coordinates of the four corners of the rectangle. I know the coordinates of the centre of the rectangle, I know its width, its height, the y distance between the highest and lowest point and the x distance between the farthest left and farthest right point as well as knowing the rotation.
My code currently looks like this (Object, of course, being the rectangle in question, keep in mind that when I apply this it can have any dimensions - This is just one possibility. Initial width and height are the actual length and width, while width and height referenced later are the x and y distances between the highest and lowest points and the farthest left and right points, rotation is of course rotation, and x and y are the object's centre coordinates).
import flash.events.Event;
addEventListener(Event.ENTER_FRAME, Rotate, false, 0, true);
var Radius:Number = Math.sqrt(((Object.height / 2) * (Object.height / 2)) + ((Object.width / 2) * (Object.width / 2)));
function Rotate(event:Event)
{
Object.rotation += 1;
Marker1.x = Math.sqrt((Radius * Radius) - ((Object.height / 2) * (Object.height / 2))) + Object.x;
Marker2.x = - Math.sqrt((Radius * Radius) - ((Object.height / 2) * (Object.height / 2))) + Object.x;
Marker3.y = Math.sqrt((Radius * Radius) - ((Object.width / 2) * (Object.width / 2))) + Object.y;
Marker4.y = - Math.sqrt((Radius * Radius) - ((Object.width / 2) * (Object.width / 2))) + Object.y;
Marker1.y = Object.y + (Object.height / 2);
Marker2.y = Object.y - (Object.height / 2);
Marker3.x = Object.x + (Object.width / 2);
Marker4.x = Object.x - (Object.width / 2);
}
As you can see I am attempting to use circle geometry to place four small circles (Markers 1-4) at the corners of the rectangle, just for testing purposes to confirm that I have gathered the correct coordinates. Problem is, the coordinates will always be placed in either +x and +y or -x and -y, but never the other two quadrants of the graph. I can't figure out a simple way of dynamically simulating the +- of the quadratic equation in the program. Does anyone know of a way to find these four points with and length, width and rotation of the rectangle?
If you represent the coordinates of the corners as offsets from the midpoint of the rectangle you can easily rotate them anti-clockwise by an angle θ with
dx' = dx × cos θ - dy × sin θ
dy' = dx × sin θ + dy × cos θ
You can then add the rotated offsets to the midpoint to recover the new coordinates of the corners.

Finding a central angle from a circle segment area

I'm trying to divide a circle into 2 segments based on 2 percentages. Like a pie chart but creating the segments with a single vertical slice.
I've found this formula for area, but haven't been able to solve for C (central angle) when I know the radius and area:
(R(squared) / 2) * ( ((pi/180)* C) - sin(C) )
Once I've got C I can use cos, tan and R(radius) to find my x and y points on the circle.
At first I thought I could simply multiply 180 * (smallerPercent / 50), but I realized that's a 'no'.
This is a good application for Newton's method. The following C program can easily be modified to
solve the problem. You can change it to calculate the desired area as a percentage of the area of
the circle, or calculate the desired area separately and enter it.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double chordangle(double r,double a)
{
double x = a/2.0;
do{
x = ((x * r * r / M_PI) - (sin(x) * r * r / 2.0) - a ) /
(r * r / M_PI - (r * r / 2.0) * cos(x));
}while(((x * r * r / M_PI) - (sin(x) * r * r / 2.0 ) - a) > 1e-11);
return x;
}
int main()
{
double a,r;
printf("Enter radius: ");
if(scanf("%lf",&r)!=1)
{
printf("You must enter a number.\n");
exit(1);
}
printf("Enter desired area of slice: ");
if(scanf("%lf",&a)!=1)
{
printf("You must enter a number.\n");
exit(1);
}
printf("The angle in radians is %lf.\n",chordangle(r,a));
printf("The angle in degrees is %lf.\n",chordangle(r,a)*180.0/M_PI);
return 0;
}
I have updated this answer (the original is at the very bottom).
You already know the radius of the circle, it's area (PI * r squared) and the area of the segment you are trying to construct (smallerPercentage / 100 * areaOfCircle).
If I understand the problem correctly, there is no formula to work out the angle that is required to create a segment of a given area and radius.
However all is not lost.
If you knew the angle you could also work out the area with the formula you already have.
A = 0.5 * r squared * ( ((PI/180) * Θ) - sin(Θ)) where Θ is the angle.
So, the only solution is to start making methodical guesses at Θ and see if the area calculated matches what you are expecting (within a certain tolerance).
And given that the percentage will be less than 50 (and greater than 0) then: 0 < angle < 180.
So, I would make my first guess at 90 degrees. If the area is too big guess again at 45, too small try 135. Keep halving the size each time and add or subtract it from the previous angle. Keep narrowing it down until you get an area that is within a tolerance of the area you are expecting. Less than 10 guesses should get you there.
I think this is called the "1/4 Tank dipstick problem": see: Link
I hope this helps.
This was my original answer, before I properly understood what you were trying to do:
I'm not sure I fully understand what you are trying to achieve, but you can work out the angles you want (in degrees) like this:
smallAngle = 360/100 * smallerPercentage;
largeAngle = 360 - smallAngle;
And you can always multiply degrees by (PI/180) to get radians.

Find the last co-ordinate of isosceles triangle given coordinates of base and altitude

I have no clue about trigonometry, despite learning it in school way back when, and I figure this should be pretty straightforward, but trawling through tons of trig stuff on the web makes my head hurt :) So maybe someone could help me...
The title explains exactly what I want to do, I have a line:
x1,y1 and x2,y2
and want a function to find x3,y3 to complete an isosceles triangle, given the altitude.
Just to be clear, the line x1,y2 -> x2,y2 will be the base, and it will not be aligned any axis (it will be at a random angle..)
Does anyone have a simple function for this??
construct a normal to the vector (x1,y1)->(x2,y2). place it at the midpoint ((x1+x2)/2,(y1+y2)/2) and go out a distance h.
the normal will look like (-(y2-y1),x2-x1). make this a unit vector (http://en.wikipedia.org/wiki/Unit_vector).
add h times this unit vector to the midpoint.
The third point is on the perpendicular bisector of your base, and is altitude units away from the line.
Calculate the midpoint of the base by averaging the x and y coordinates.
Calculate the slope of your altitude: -dx/dy (perpendicular to dy/dx). You now have your line (point and slope).
y - my = -dx/dy * (x - mx)
Substitute your variables in the distance formula: d = sqrt(dx^2 + dy^2)
d = sqrt((x - mx)^2 + (y - my)^2)
d = sqrt((x - mx)^2 + (-dx/dy * (x - mx))^2)
d^2 = (x - mx)^2 + (-dx/dy * (x - mx))^2
d^2 - (x - mx)^2 = (-dx/dy * (x - mx))^2
±sqrt(d^2 - (x - mx)^2) = -dx/dy * (x - mx)
±sqrt(d^2 - (x - mx)^2) * dy/dx = x - mx
±sqrt(d^2 - (x - mx)^2) * dy/dx + mx = x
x = ±sqrt(d^2 - (x - mx)^2) * dy/dx + mx
Calculate the other variable (y here) using your line equation (from #2).
You now have two points; pick whichever you want...
In pseudocode:
dx = x1 - x2
midpoint = ((x1 + x2) / 2, (y1 + y2) / 2)
slope = -dx / (y1 - y2)
x = sqrt(altitude*altitude - dx*dx) / slope + midpoint.x
y = slope * (x - midpoint.x) + midpoint.y
This is probably not the most optimal method. Not sure if it even works. xD
Al I can remember is that an isosceles triangle will have sides of equal length, and equal angles at the base. If you have the height, then you have the final coordinate because this will be the point of intersection, right?