Simple Trigonometry? - geometry

EDIT - Thanks for all the answers everyone. I think I accidentally led you slightly wrong as the square in the picture below should be a rectangle (I see most of you are referencing squares which seems like it would make my life a lot easier). Also, the x/y lines could go in any direction, so the red dot won't always be at the top y boundary. I was originally going for a y = mx + b solution, but then I got stuck trying to figure out how I know whether to plug in the x or the y (one of them has to be known, obviously).
I have a very simple question (I think) that I'm currently struggling with for some reason. I'm trying to have a type of minimap in my game which shows symbols around the perimeter of the view, pointing towards objectives off-screen.
Anyway, I'm trying to find the value of the red point (while the black borders and everything in green is known):
It seems like simple trigonometry, but for some reason I can't wrap my head around it. I just need to find the "new" x value from the green point to the red point, then I can utilize basic math to get the red point, but how I go about finding that new x is puzzling me.
Thanks in advance!

scale = max(abs(x), abs(y))
x = x / scale
y = y / scale
This is the simple case, for a square from (-1, -1) to (1, 1). If you want a different sized square, multiply the coordinates by sidelen / 2.
If you want a rectangle instead of a square, use the following formula. (This is another solution to the arbitrarily-sized square version)
scale = max(abs(x) / (width / 2), abs(y) / (height / 2))
x = x / scale
y = y / scale

Let's call the length of one side of the square l. The slope of the line is -y/x. That means, if you move along the line and rise a distance y toward the top of the square, then you'll move a distance x to the left. But since the green point is at the center of the square, you can rise only l/2. You can express this as a ratio:
-y -l/2
——— = ———
x d
Where d is the distance you'll move to the left. Solving for d, we have
d = xl/2y
So if the green dot is at (0, 0), the red dot is at (-l/2, xl/2y).

All you need is the angle and the width of the square w.
If the green dot is at (0,0), then the angle is a = atan(y/x), the y-coordinate of the dot is w/2, and therefore the x-coordinate of the dot is tan(1/a) * (w/2). Note that tan(1/a) == pi/2 - tan(a), or in other words the angle you really want to plug into tan is the one outside the box.
Edit: yes, this can be done without trig, too. All you need is to interpolate the x-coordinate of the dot on the line. So you know the y-coordinate is w/2, then the x-coordinate is (w/2) * x/y. But, be careful which quadrant of the square you're working with. That formula is only valid for -y<x<y, otherwise you want to reverse x and y.

Related

Is it accurate to conclude the radius of a circle given 4 bazier curves in svg?

I have used svg2paths2, and wanted to figure out what is the position and radius of a circle, I have noticed the circle is consructed by 4 CubicBezier, as follow:
Path(CubicBezier(start=(127.773+90.5469j), control1=(127.773+85.7656j), control2=(123.898+81.8906j), end=(119.121+81.8906j)),
CubicBezier(start=(119.121+81.8906j), control1=(114.34+81.8906j), control2=(110.465+85.7656j), end=(110.465+90.5469j)),
CubicBezier(start=(110.465+90.5469j), control1=(110.465+95.3281j), control2=(114.34+99.1992j), end=(119.121+99.1992j)),
CubicBezier(start=(119.121+99.1992j), control1=(123.898+99.1992j), control2=(127.773+95.3281j), end=(127.773+90.5469j)))
I have read the standard approach is to divide the circle into four equal sections, and fit each section to a cubic Bézier curve.
So I was wondering is it accurate to say the Radius of the circle is
(q1.start.real - q3.start.real)/2
or
(q2.start.imag - q4.start.imag)/2
And the center of the circle is:
c_x = (q1.start.real + q1.end.real) / 2
c_y = (q1.start.imag + q1.end.imag) / 2
Thank you!
I'm assuming you are using svg.path library in python, or svg2paths2 is related.
from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, Close
path = Path(CubicBezier(start=(127.773+90.5469j), control1=(127.773+85.7656j), control2=(123.898+81.8906j), end=(119.121+81.8906j)),
CubicBezier(start=(119.121+81.8906j), control1=(114.34+81.8906j), control2=(110.465+85.7656j), end=(110.465+90.5469j)),
CubicBezier(start=(110.465+90.5469j), control1=(110.465+95.3281j), control2=(114.34+99.1992j), end=(119.121+99.1992j)),
CubicBezier(start=(119.121+99.1992j), control1=(123.898+99.1992j), control2=(127.773+95.3281j), end=(127.773+90.5469j)))
q1 = path[0]
q2 = path[1]
q3 = path[2]
q4 = path[3]
.real is the X coordinate
.imag is the Y coordinate
There's a very slight error in accuracy in the drawing program you are using and it's not at all an issue unless you want extreme accuracy.
(q1.start.real - q3.start.real) / 2 # 8.6539 is the radius in this case.
(q4.start.imag - q2.start.imag)/2 # 8.6543 is also the radius.
(q1.start.real - q1.end.real) # 8.6539 is again also the radius.
This accesses the same property, q1 of path and I' prefer it to the two above ways because it's accessing one property not two.
Below shown by green circle in diagram
c_x = (q1.start.real + q1.end.real) / 2 # 123.447 not center x
c_y = (q1.start.imag + q1.end.imag) / 2 # 86.21875 not center y
Below shown by red circle in diagram
c_x = q1.end.imag # 119.121 this is center x
c_y = q1.start.real # 90.5469 this is center y
To explain how serious the error in accuracy, the pink circle uses 8.6543 radius, below it is 8.6539 in green, perhaps viewable with an extreme zoom. But this does illustrate how important or not the decimal points can be.
Consider using numbers under 100 and as few decimal points as possible, especially understanding a new idea. Shorter text-length numbers vastly improves readability, understanding no end.
I often use just numbers below ten.
Note: you are drawing the circle counter-clockwise. Clockwise is the usual way.

Calculate the number of circles that fit on the circumference of another circle

I'm looking for an algorithm (or pseudo code) that can calculate the maximum number of (smaller) circles with diameter "s" that can be squeezed into the circumference of another (larger) circle with radius "r" ...
Image: http://teasy.space/images/terracolony-squeezingcircles2.jpg
You can alternate between radius/diameter etc if you wish -- as these are the only 2 parameters (other than the center (large circle) coordinate) that i have, i.e. that are known ...
The outer circles may not overlap but can fit "snug" together ...
After various upgrades to my routine through the years, I'm currently using an algorithm that is not perfect (and it needs to be accurate or the galaxy breaks down lol)
which does a broad interpolation between small outside circle diameter and large inside circle circumference, to somewhat accurately plot the circle count in a polygon style fitting pattern, which causes problems (i.e. overlaps) when using larger outside circles ...
; try to fit a random number of circles
num_Circles = Rand( min,max )
; check if the number of circles exceed the maximum that can fit
If num_Circles * SmallCircle_Diameter > LargeCircle_Circumference
; adjust the amount accordingly
num_Circles = LargeCircle_Circumference / SmallCircle_Diameter
End If
Another assumption is that the size of the smaller outer circles never exceeds that of the larger inner circle ...
something less to worry about ;)
I'm using this algorithm for one of my projects called Terra Colony, based on Gravity Well, a 2D space/gravity realtime colonization simulation game with moons, planets, stars, black/white holes, etc
Image: http://teasy.space/images/terracolony-squeezingcircles1.jpg
This is an issue that has plagued this project for over a decade!
Hopefully you can point me in the right direction :D
I have previously done many experiments and wrote different programs to find a solution, and have traveled the internet looking for formulas and solutions which in the end are very close, but not close enough! :P
Thank you! <3
Teasy
P.S. I tried to add the tag "circumference" but it apparently requires "1500 reputation" (points i guess, maybe to prevent spam)
There is formula that establishes relation between radius of big circle R, radius of small circle r and number of (touching) small circles N
R = r / Sin(Pi/N)
So maximum number of small circles might be found as
Sin(Pi/N) = r / R
Pi / N = arcsin(r / R)
and finally
N = Pi / arcsin(r / R)
Example:
R=5
r=2.5
so
N = Pi / arcsin(1/2) =
Pi / (Pi/6) =
6
Given the diam. of the small circle 'd' and the number of them 'c'
then the dia. of the large circle 'D' is
D=d/sin(180/c)

How to know if a point belongs more or less to a circle?

I know the formula to know if a point is inside, outside and on a circle : https://math.stackexchange.com/q/198769 This quote explains that we must compare d to r (please read the quote, it's only 5 lines).
But I just want to know if a point is ON a circle. Moreover, and that's the real problem : if a point is a bit inside/outside a circle, I want to consider it as ON the circle.
How could I do that ? I tried to delimit d-r (ie. : the comparison) in a range. Example :
if(d-r > -100 && d-r < 100) { point is on the circle }
It works, with -100 and 100, for circles with a little radius (ie. : ALL the points that are a bit outside/inside the circle are considered as being on the circle).
But for circles for a big radius, only SOME points are considered as being on the circle (ie. : only some of the points that are a bit outside/inside the circle are considered as being on the circle)...
So I would want that ALL the points that are a bit outside/inside the circle are considered as being on the circle, independently of the circle's radius. How ?
Your comparison for absolute difference might be written shorter as
if Abs(d - r) < delta (i.e. 100) ...
But seems you need relative difference depending on circle radius like this:
if Abs(d - r) / r < reldelta (i.e. 0.001) ...
From a probabilistic perspective, you could define a sort of distance map (as proposed by #Mbo) adopting the relative distance and use it to build a probability distribution on each point. The probability would represent a sort of likelihood of the point to belong to the circle. Intuitively, the closer the point, the more likely it is to be part of the circle. For example:
rel_d = (d-r)/r;
// P(x on the circle) = 1 - rel_d
if(rel_d < 1){
P_on_circle = 1 - rel_d;
}else{
P_on_circle = 0;
}

Finding the original position of a point on an image after rotation

I have the x, y co-ordinates of a point on a rotated image by certain angle. I want to find the co-ordinates of the same point in the original, non-rotated image.
Please check the first image which is simpler:
UPDATED image, SIMPLIFIED:
OLD image:
Let's say the first point is A, the second is B and the last is C. I assume you have the rotation matrice R (see Wikipedia Rotation Matrix if not) et the translation vector t, so that B = R*A and C = B+t.
It comes C = R*A + t, and so A = R^1*(C-t).
Edit: If you only need the non rotated new point, simply do D = R^-1*C.
First thing to do is defining the reference system (how "where the points lies with respect to each image" will be translated into numbers). I guess that you want to rely on a basic 2D reference system, given by a single point (a couple of X/Y values). For example: left/lower corner (min. X and min. Y).
The algorithm is pretty straightforward:
Getting the new defining reference point associated with the
rotated shape (min. X and min. Y), that is, determining RefX_new and
RefY_new.
Applying a basic conversion between reference systems:
X_old = X_new + (RefX_new - RefX_old)
Y_old = Y_new + (RefY_new -
RefY_old)
----------------- UPDATE TO RELATE FORMULAE TO NEW CAR PIC
RefX_old = min X value of the CarFrame before being rotated.
RefY_old = max Y value of the CarFrame before being rotated.
RefX_new = min X value of the CarFrame after being rotated.
RefY_new = max Y value of the CarFrame after being rotated.
X_new = X of the point with respect to the CarFrame after being rotated. For example: if RefX_new = 5 with respect to absolute frame (0,0) and X of the point with respect to this absolute frame is 8, X_new would be 3.
Y_new = Y of the point with respect to CarFrame after being rotated (equivalently to point above)
X_old_C = X_new_C(respect to CarFrame) + (RefX_new(CarFrame_C) - RefX_old(CarFrame_A))
Y_old_C = Y_new_C(respect to CarFrame) + (RefY_new(CarFrame_C) - RefY_old(CarFrame_A))
These coordinates are respect to the CarFrame and thus you might have to update them with respect to the absolute frame (0,0, I guess), as explained above, that is:
X_old_D_absolute_frame = X_old_C + (RefX_new(CarFrame_C) + RefX_global(i.e., 0))
Y_old_D_absolute_frame = Y_old_C + (RefY_new(CarFrame_C) + RefY_global(i.e., 0))
(Although you should do that once the CarFrame is in its "definitive position" with respect to the global frame, that is, on picture D (the point has the same coordinates with respect to the CarFrame in both picture C and D, but different ones with respect to the global frame).)
It might seem a bit complex put in this way; but it is really simple. You have just to think carefully about one case and create the algorithm performing all the actions. The idea is extremely simple: if I am on 8 inside something which starts in 5; I am on 3 with respect to the container.
------------ UPDATE IN THE METHODOLOGY
As said in the comment, these last pictures prove that the originally-proposed calculation of reference (max. Y/min. X) is not right: it shouldn't be the max./min. values of the carFrame but the minimum distances to the closer sides (= perpendicular line from the left/bottom side to the point).
------------ TRIGONOMETRIC CALCS FOR THE SPECIFIC EXAMPLE
The algorithm proposed is the one you should apply in any situation. Although in this specific case, the most difficult part is not moving from one reference system to the other, but defining the reference point in the rotated system. Once this is done, the application to the non-rotated case is immediate.
Here you have some calcs to perform this action (I have done it pretty quickly, thus better take it as an orientation and do it by your own); also I have only considered the case in the pictures, that is, rotation over the left/bottom point:
X_rotated = dx * Cos(alpha)
where dx = X_orig - (max_Y_CarFrame - Y_Orig) * Tan(alpha)
Y_rotated = dy * Cos(alpha)
where dy = Y_orig - X_orig * Tan(alpha)
NOTE: (max_Y_CarFrame - Y_Orig) in dx and X_orig in dy expect that the basic reference system is 0,0 (min. X and min. Y). If this is not the case, you would have to change this variables.
The X_rotated and Y_rotated give the perpendicular distance from the point to the closest side of the carFrame (respectively, left and bottom side). By applying these formulae (I insist: analyse them carefully), you get the X_old_D_absolute_frame/Y_old_D_absolute_frame that is, you have just to add the lef/bottom values from the carFrame (if it is located in 0,0, these would be the final values).

How to calculate angle between two direction vectors that form a closed/open shape?

I am trying to figure out the correct trig. eq./function to determine the following:
The Angle-change (in DEGREES) between two DIRECTION VECTORS(already determined), that represent two line-segment.
This is used in the context of SHAPE RECOGTNITION (hand drawn by user on screen).
SO basically,
a) if the user draws a (rough) shape, such as a circle, or oval, or rectangle etc - the lines that makes up that shape are broken down in to say.. 20 points(x-y pairs).
b) I have the DirectionVector for each of these LINE SEGMENTS.
c) So the BEGINNING of a LINE SEGMENT(x0,y0), will the END points of the previous line(so as to form a closed shape like a rectangle, let's say).
SO, my question is , given the context(i.e. determinign the type of a polygon), how does one find the angle-change between two DIRECTION VECTORS(available as two floating point values for x and y) ???
I have seen so many different trig. equations and I'm seeking clarity on this.
Thanks so much in advance folks!
If (x1,y1) is the first direction vector and (x2,y2) is the second one, it holds:
cos( alpha ) = (x1 * x2 + y1 * y2) / ( sqrt(x1*x1 + y1*y1) * sqrt(x2*x2 + y2*y2) )
sqrt means the square root.
Look up http://en.wikipedia.org/wiki/Dot_product
Especially the section "Geometric Representation".
You could try atan2:
float angle = atan2(previousY-currentY, previousX-currentY);
but also, as the previous answers mentioned, the
angle between two verctors = acos(first.dotProduct(second))
I guess you have the vector as three points (x_1, y_1), (x_2, y_2) and (x_3, y_3).
Then you can move the points so that (x_1, y_1) == (0, 0) by
(x_1, y_1) = (x_2, y_2) - (x_1, y_1)
(x_2, y_2) = (x_3, y_3) - (x_1, y_1)
Now you have this situation:
Think of this triangle as two right-angled triangles. The first one has the angle alpha and a part of beta, the second right-angled triangle has the other part of beta.
Then you can apply:
You can calculate alpha like this:
If I understand you correctly, you may just evaluate the dot product between two vectors and take the appropriate arccos to retrieve the angle between these vectors.

Resources