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

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?

Related

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

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).

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.

Drawing an arrow at the end point of the line using line slope

I am developing a white board application which allows the user to draw line with arrow head (some like Microsoft Word line with arrow feature). I am using graphics property along with lineTo() method to draw a line. Now i have to draw a angular arrow on the last point of line. I am drawing the arrow by connecting the points around last points. As 360 line can pass through this point and each line can have a different angle of arrow. Please suggest me the way to calculating these point around the last point.
I've been doing something myself, and I needed it to look a bit nicer than just a triangle, and use relatively inexpensive calculations (as few calls to other functions as possible, like Math trigonometry). Here it is:
public static function DrawArrow(ax:int, ay:int, bx:int, by:int):void
{
// a is beginning, b is the arrow tip.
var abx:int, aby:int, ab:int, cx:Number, cy:Number, dx:Number, dy:Number, ex:Number, ey:Number, fx:Number, fy:Number;
var size:Number = 8, ratio:Number = 2, fullness1:Number = 2, fullness2:Number = 3; // these can be adjusted as needed
abx = bx - ax;
aby = by - ay;
ab = Math.sqrt(abx * abx + aby * aby);
cx = bx - size * abx / ab;
cy = by - size * aby / ab;
dx = cx + (by - cy) / ratio;
dy = cy + (cx - bx) / ratio;
ex = cx - (by - cy) / ratio;
ey = cy - (cx - bx) / ratio;
fx = (fullness1 * cx + bx) / fullness2;
fy = (fullness1 * cy + by) / fullness2;
// draw lines and apply fill: a -> b -> d -> f -> e -> b
// replace "sprite" with the name of your sprite
sprite.graphics.clear();
sprite.graphics.beginFill(0xffffff);
sprite.graphics.lineStyle(1, 0xffffff);
sprite.graphics.moveTo(ax, ay);
sprite.graphics.lineTo(bx, by);
sprite.graphics.lineTo(dx, dy);
sprite.graphics.lineTo(fx, fy);
sprite.graphics.lineTo(ex, ey);
sprite.graphics.lineTo(bx, by);
sprite.graphics.endFill();
}
You can also add the line color and thickness to the argument list, and maybe make it a member function of an extended Sprite, and you have a pretty nice, versatile function :) You can also play a bit with the numbers to get different shapes and sizes (small changes of fullness cause crazy changes in look, so careful :)). Just be careful not to set ratio or fullness2 to zero!
If you store the start and end point of the line, adding the arrow head should be relatively simple. If you subtract the end point coordinates from the start point coordinates, you will get the arrow direction vector (let's call it D). With this vector, you can determine any point on the line between the two points.
So, to draw the arrow head, you would need to determine a point (P1) on the segment that has a specific distance (d1) from the end point, determine a line that passes through it, and is perpendicular to D. And finally get a point (P2) that has a distance (d2) from the previously determined point. You can then determine the point that is symmetrical to P2, relative to D.
You will thus have an arrow head the length of d1 and a base with of 2 * d2.
Some additional information and a few code examples here: http://forums.devx.com/archive/index.php/t-74981.html

AS3 - Y Velocity 6.123031769111886E-17

When given 0,0 to 0,5, the y velocity becomes that number and breaks my code. I know I must have done something wrong as I just copy and pasted code (since I am horrible at maths)..
This is how I calculate the numbers:
var radian = Math.atan2(listOfNodes[j].y - listOfNodes[i].y,listOfNodes[j].x - listOfNodes[i].x);
var vy = Math.cos(radian);
var vx = Math.sin(radian);
Thanks
There i am assuming the velocity vector is FROM 0,0 TO 0,5. And 0,0 is i and 0,5 is j.
In that case the velocity vector is only along y and the y component should be 5 and x component 0. It is coming as opposite because,
cos(radian) whould be x velocity component and sin(radian) the y compunent.
And the number 6.123031769111886E-17 is actually returned in place of 0.
Look at the following figure:
Also as can be seen from the figure you do not need the trigonometric computations at all.
You can simply get the x and y components as follows:
// y2 - y1
var vy = listOfNodes[j].y - listOfNodes[i].y;
// x2 - x1
var vx = listOfNodes[j].x - listOfNodes[i].x;
This will avoid the floating point inaccuracy caused by the trig finctions due to which you are seeing 6.123031769111886E-17 instead of 0.
You only need to use atan2 if you actually need the angle θ in your code.
Update:
Well if you need only unit (normalized) vector's components you can divide the vx and vy with the length of the original vector. Like this:
// y2 - y1
var vy = listOfNodes[j].y - listOfNodes[i].y;
// x2 - x1
var vx = listOfNodes[j].x - listOfNodes[i].x;
// vector magnitude
var mag = Math.sqrt(vx * vx + vy * vy);
// get unit vector components
vy /= mag;
vx /= mag;
Using the above you will get the exactly the same results as you are getting from trig sin and cos functions.
But if you still need to use the original code and want to make 6.12...E-17 compare to 0, you can use the epsilon technique for comparing floats. So you can compare any value within epsilon's range from 0, using flllowing code:
function floatCompare(a:Number, b:Number, epsilon:Number):Boolean{
return (a >= (b - epsilon) && a <= (b + epsilon));
}
// To check for zero use this code, here i'm using 0.0001 as epsilon
if(floatCompare(vx, 0, 0.0001)){
// code here
}
So any deviation in the range of [b-epsilon, b+epsilon] would successfully compare to b. This is essential in case of floating point arithmetic.

Triangle Trigonometry (ActionScript 3)

I am trying to write a formula in ActionScript 3 that will give me var "z" (please see image below) in degrees, which I will then convert to radians.
I will already know the value of vars "x" and "y". Using trigonometry, how can I calculate the length of the hypotenuse and therefore the variable angle of var z? A solution in either AS3 or psuedocode would be very helpful. Thanks.
What you need is this:
var h:Number = Math.sqrt(x*x + y*y);
var z:Number = Math.atan2(y, x);
That should give you the angle in radians, you might need to swap x/y and possibly add or remove 90 degrees but it should do the trick! (Note that you don't even need h to get z when you're using atan2)
I use multiplication instead of Math.pow() just because Math is pretty slow, you can do:
var h:Number = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
And it should be exactly the same.
z is equivalent to 180 - angle of yH. Or:
180 - arctan(x/y) //Degrees
pi - arctan(x/y) //radians
Also, if actionscript's math libraries have it, use arctan2, which takes both the x and y and deals with signs correctly.
The angle you want is the same as the angle opposed to the one wetween y and h.
Let's call a the angle between y and h, the angle you want is actually 180 - a or PI - a depending on your unit (degrees or radians).
Now geometry tells us that:
cos(a) = y/h
sin(a) = x/h
tan(a) = x/y
Using tan(), we get:
a = arctan(x/y)
As we are looking for 180 - a, you should compute:
180 - arctan(x/y)
What #Patrick said, also the hypotenuse is sqrt(x^2 + y^2).