Find third point with circumcenter and two points of a triangle - geometry

How to calculate the third point of the isosceles triangle using JAVA, given its two points and the circumcenter. There will be two solutions for this, and it is sufficient for me if I get the shortest one from the points A and B.

If AB is the base of isosceles triangle (AC=BC), then solution is rather simple.
Given points A, B, CC (circumcenter)
Circumradius is
R = Length(CC-A) = Sqrt((CC.X - A.X)^2 + (CC.Y - A.Y)^2)
Edit: changed direction vector calculation to avoid ambiguity:
Middle point of AB
M = ((A.X + B.X)/2, (A.Y + B.Y)/2)
Direction vector from CC to vertice C
D = (CC.X - M.X, CC.Y - M.Y)
Normalized (unit) direction vector
uD = (D.X / Length(D), D.Y / Length(D))
Vertice C coordinates
C = (CC.X + R * uD.X, CC.Y + R * uD.Y)

Related

How to find centers of two circle when their intersecting points and corresponding radius is given?

I was reading chapter 7 of "Competitive Programming 3" by Steven and Felix Halim. I then found this problem, given in picture:
Here two intersecting points of two circles and corresponding radius are also given. I have to find centres of two circles. They have given the solution code. But I didn't understand the technique behind it. The given code is:
I have searched many times, but I didn't find. Can anyone explain the technique?
Anyway, thanks in advance :)
Let's first visualize variables d2 and h defined in the code:
As we can see, d2 stands for the square of the distance between p1 and p2. Let's put d = sqrt(d2). Then d^2 = d2.
Using Pythagoras: r^2 = h^2 + d^2/4. Hence, h^2 = r^2 - d^2/4.
The unitary (norm = 1) vector in the direction of the line joining p1 and p2 is:
v := (p2 - p1)/d = (p2.x - p1.x, p2.y - p1.y)/d.
its perpendicular is
w := (p2.y - p1.y, p1.x - p2.x)/d
Now we can express c1 as a point in the perpendicular direction:
c1 = q + w*h = (p1 + p2)/2 + w*h,
because w has norm 1 and h is precisely the distance between c1 and q. Therefore,
c1 = (p1.x + p2.x, p1.y + p2.y)/2 + (p2.y - p1.y, p1.x - p2.x)*h/d
where
h/d = sqrt(r^2 - d^2/4)/d = sqrt(r^2/d2 - 1/4)
which explains the code.
Notes
From the picture that r is always ge than d/2. Thus, r^2 ≥ d^2/4 or (r/d)^2 ≥ 1/4 and there is no need to check whether det < 0, because it never is (provided the circles intersect).
The derivation above will actually produce two solutions for c1, one to the right of the blue line from p1 to p2, which is the one in the drawing, and another on the left of said line. In fact, these correspond to the equations
c1 = q ± w*h = q + w*(±h)
In order to decide whether we should use +h or -h, we can apply one of the well-known criteria for establishing whether a point lies on the left or the right of a directed segment. For example, we could compute the sign of the determinant
| 1 p1.x p1.y |
D = | 1 p2.x p2.y | = (p2.x-p1.x)(c1.y-p1.y) - (p2.y-p1.y)(c1.x-p1.x)
| 1 c1.x c1.y |
which will have a sign for +h and the opposite for -h. The value of h that makes D < 0 is the one that leaves c1 on the right of the segment from p1 to p2.
Apply Pythagoras in the right triangles. This gives you the distances between the midpoint of p1p2 and the centers.
From unit vectors parallel then orthogonal to p1p2, the offset vectors are easily obtained.

Line segment intersection

I found this code snippet on raywenderlich.com, however the link to the explanation wasn't valid anymore. I "translated" the answer into Swift, I hope you can understand, it's actually quite easy even without knowing the language. Could anyone explain what exactly is going on here? Thanks for any help.
class func linesCross(#line1: Line, line2: Line) -> Bool {
let denominator = (line1.end.y - line1.start.y) * (line2.end.x - line2.start.x) -
(line1.end.x - line1.start.x) * (line2.end.y - line2.start.y)
if denominator == 0 { return false } //lines are parallel
let ua = ((line1.end.x - line1.start.x) * (line2.start.y - line1.start.y) -
(line1.end.y - line1.start.y) * (line2.start.x - line1.start.x)) / denominator
let ub = ((line2.end.x - line2.start.x) * (line2.start.y - line1.start.y) -
(line2.end.y - line2.start.y) * (line2.start.x - line1.start.x)) / denominator
//lines may touch each other - no test for equality here
return ua > 0 && ua < 1 && ub > 0 && ub < 1
}
You can find a detailed segment-intersection algorithm
in the book Computational Geometry in C, Sec. 7.7.
The SegSegInt code described there is available here.
I recommend avoiding slope calculations.
There are several "degenerate" cases that require care: collinear segments
overlapping or not, one segment endpoint in the interior of the other segments,
etc. I wrote the code to return an indication of these special cases.
This is what the code is doing.
Every point P in the segment AB can be described as:
P = A + u(B - A)
for some constant 0 <= u <= 1. In fact, when u=0 you get P=A, and you getP=B when u=1. Intermediate values of u will give you intermediate values of P in the segment. For instance, when u = 0.5 you will get the point in the middle. In general, you can think of the parameter u as the ratio between the lengths of AP and AB.
Now, if you have another segment CD you can describe the points Q on it in the same way, but with a different u, which I will call v:
Q = C + v(D - C)
Again, keep in mind that Q lies between C and D if, and only if, 0 <= v <= 1 (same as above for P).
To find the intersection between the two segments you have to equate P=Q. In other words, you need to find u and v, both between 0 and 1 such that:
A + u(B - A) = C + v(D - C)
So, you have this equation and you have to see if it is solvable within the given constraints on u and v.
Given that A, B, C and D are points with two coordinates x,y each, you can open the equation above into two equations:
ax + u(bx - ax) = cx + v(dx - cx)
ay + u(by - ay) = cy + v(dy - cy)
where ax = A.x, ay = A.y, etc., are the coordinates of the points.
Now we are left with a 2x2 linear system. In matrix form:
|bx-ax cx-dx| |u| = |cx-ax|
|by-ay cy-dy| |v| |cy-ay|
The determinant of the matrix is
det = (bx-ax)(cy-dy) - (by-ay)(cx-dx)
This quantity corresponds to the denominator of the code snippet (please check).
Now, multiplying both sides by the cofactor matrix:
|cy-dy dx-cx|
|ay-by bx-ax|
we get
det*u = (cy-dy)(cx-ax) + (dx-cx)(cy-ay)
det*v = (ay-by)(cx-ax) + (bx-ax)(cy-ay)
which correspond to the variables ua and ub defined in the code (check this too!)
Finally, once you have u and v you can check whether they are both between 0 and 1 and in that case return that there is intersection. Otherwise, there isn't.
For a given line the slope is
m=(y_end-y_start)/(x_end-x_start)
if two slopes are equal, the lines are parallel
m1=m1
(y1_end-y_start)/(x1_end-x1_start)=(y2_end-y2_start)/(x2_end-x2_start)
And this is equivalent to checking that the denominator is not zero,
Regarding the rest of the code, find the explanation on wikipedia under "Given two points on each line"

TI-BASIC (TI-84) Solving for the Sides of a Triangle

Could someone tell me if I've coded this correctly? This is my code for solving for the sides of a triangle given its perimeter, altitude, and angle (for the algebra see http://www.analyzemath.com/Geometry/challenge/triangle_per_alt_angle.html)
Prompt P
Prompt H
Prompt L [the angle]
(HP^2)/(2H(1+cos(L))+2Psin(L))→Y
(-P^2-2(1+cos(L))Y/(-2P)→Z
(Z+sqrt(Z^2-4Y))/2→N
[The same as above but Z-sqrt...]→R
If N>0
N→U
If R>0
R→U
Y/U→V
sqrt(U^2+V^2-2UVcos(L))→W
Disp U
Disp V
Disp W
Also, how would I fix this so that I can input angle = 90?
Also, in this code does it matter if the altitude is the one between b and c (refer to the website again)?
Thanks in advance
The code already works with L=90°.
Yes, the altitude must be the distance from point A to the base a between points B and C, forming a right-angle with that base. The derivation made that assumption, specifically with respect to the way it used h and a in the second area formula 1/2 h a. That exact formula would not apply if h was drawn differently.
The reason your second set of inputs resulted in a non-real answer is that sometimes a set of mathematical parameters can be inconsistent with each other and describe an impossible construct, and your P, h, and L values do exactly that. Specifically, they describe an impossible triangle.
Given an altitude h and angle L, the smallest perimeter P that can be achieved is an isosceles triangle split down the middle by h. With L=30, this would have perimeter P = a + b + c = 2h tan15 + h/cos15 + h/cos15, which, plugging in your h=3, results in P=7.819. You instead tried to use P=3+sqrt(3)=4.732. Try using various numbers less than 7.819 (plus a little; I've rounded here) and you'll see they all result in imaginary results. That's math telling you you're calculating something that cannot exist in reality.
If you fill in the missing close parenthesis between the Y and the / in line 5, then your code works perfectly.
I wrote the code slightly differently from you, here's what I did:
Prompt P
Prompt H
Prompt L
HP²/(2H(1+cos(L))+2Psin(L))→Y
(HP-Ysin(L))/H→Z
Z²-4Y→D
If D<0:Then
Disp "IMAGINARY"
Stop
End
(Z+√(D))/2→C
Y/C→B
P-(B+C)→A
Disp A
Disp B
Disp C
Edit: #Gabriel, there's nothing special (with respect to this question) about the angles 30-60-90; there is an infinite number of sets of P, h, and L inputs that describe such triangles. However, if you actually want to arrive at such triangles in the answer, you've actually changed the question; instead of just knowing one angle L plus P and h, you now know three angles (30-60-90) plus P and h. You've now over-specified the triangle, so that it is pretty well certain that a randomly generated set of inputs will describe an impossible triangle. As a contrived example, if you specified h as 0.0001 and P as 99999, then that's clearly impossible, because a triangle with a tiny altitude and fairly unextreme angles (which 30-60-90 are) cannot possibly achieve a perimeter many times its altitude.
If you want to start with just one of P or h, then you can derive equations to calculate all parameters of the triangle from the known P or h plus the knowledge of the 30-60-90 angles.
To give one example of this, if we assume that side a forms the base of the triangle between the 90° and 60° angles, then we have L=30 and (labelling the 60° angle as B) we have h=b, and you can get simple equations for all parameters:
P = a + h + c
sin60 = h/c
cos60 = a/c
=> P = c cos60 + c sin60 + c
P = c(cos60 + sin60 + 1)
c = P/(cos60 + sin60 + 1)
b = h = c sin60
a = c cos60
Plugging in P=100 we have
c = 100/(cos60 + sin60 + 1) = 42.265
b = h = 36.603
a = 21.132
If you plug in P=100, h=36.603, and L=30 into the code, you'll see you get these exact results.
Always optimize for speed, then size.
Further optimizing bgoldst's code:
Prompt P,H,L
HP²/(2H(1+cos(L))+2Psin(L
.5(Z+√((HP-sin(L)Ans)/H)²-4Ans
{Y/C→B,P-B-Ans,Ans

find point where barycentric weights have a specific value

I have triangle: a, b, c. Each vertex has a value: va, vb, vc. In my software the user drags point p around inside and outside of this triangle. I use barycentric coordinates to determine the value vp at p based on va, vb, and vc. So far, so good.
Now I want to limit p so that vp is within range min and max. If a user chooses p where vp is < min or > max, how can I find the point closest to p where vp is equal to min or max, respectively?
Edit: Here is an example where I test each point. Light gray is within min/max. How can I find the equations of the lines that make up the min/max boundary?
a = 200, 180
b = 300, 220
c = 300, 300
va = 1
vb = 1.4
vc = 3.2
min = 0.5
max = 3.5
Edit: FWIW, so far first I get the barycentric coordinates v,w for p using the triangle vertices a, b, c (standard stuff I think, but looks like this). Then to get vp:
u = 1 - w - v
vp = va * u + vb * w + vc * v
That is all fine. My trouble is that I need the line equations for min/max so I can choose a new position for p when vp is out of range. The new position for p is the point closest to p on the min or max line.
Note that p is an XY coordinate and vp is a value for that coordinate determined by the triangle and the values at each vertex. min and max are also values. The two line equations I need will give me XY coordinates for which the values determined by the triangle are min or max.
It doesn't matter if barycentric coordinates are used in the solution.
The trick is to use the ratio of value to cartesian distance to extend each triangle edge until it hits min or max. Easier to see with a pic:
The cyan lines show how the triangle edges are extended, the green Xs are points on the min or max lines. With just 2 of these points we know the slope if the line. The yellow lines show connecting the Xs aligns with the light gray.
The math works like this, first get the value distance between vb and vc:
valueDistBtoC = vc - vb
Then get the cartesian distance from b to c:
cartesianDistBtoC = b.distance(c)
Then get the value distance from b to max:
valueDistBtoMax = max - vb
Now we can cross multiply to get the cartesian distance from b to max:
cartesianDistBtoMax = (valueDistBtoMax * cartesianDistBtoC) / valueDistBtoC
Do the same for min and also for a,b and c,a. The 6 points are enough to restrict the position of p.
Consider your triangle to actually be a 3D triangle, with points (ax,ay,va), (bx,by,vb), and (cx,cy,vc). These three points define a plane, containing all the possible p,vp triplets obtainable through barycentric interpolation.
Now think of your constraints as two other planes, at z>=max and z<=min. Each of these planes intersects your triangle's plane along an infinite line; the infinite beam between them, projected back down onto the xy plane, represents the area of points which satisfy the constraints. Once you have the lines (projected down), you can just find which (if either) is violated by a particular point, and move it onto that constraint (along a vector which is perpendicular to the constraint).
Now I'm not sure about your hexagon, though. That's not the shape I would expect.
Mathematically speaking the problem is simply a change of coordinates. The more difficult part is finding a good notation for the quantities involved.
You have two systems of coordinates: (x,y) are the cartesian coordinates of your display and (v,w) are the baricentric coordinates with respect to the vectors (c-a),(b-a) which determine another (non orthogonal) system.
What you need is to find the equation of the two lines in the (x,y) system, then it will be easy to project the point p on these lines.
To achieve this you could explicitly find the matrix to pass from (x,y) coordinates to (v,w) coordinates and back. The function you are using toBaryCoords makes this computation to find the coordinates (v,w) from (x,y) and we can reuse that function.
We want to find the coefficients of the transformation from world coordinates (x,y) to barycentric coordinates (v,w). It must be in the form
v = O_v + x_v * x + y_v * y
w = O_w + x_w * x + y_w * y
i.e.
(v,w) = (O_v,O_w) + (x_v,y_y) * (x,y)
and you can determine (O_v,O_w) by computing toBaryCoord(0,0), then find (x_v,x_w) by computing the coordinates of (1,0) and find (y_v,y_w)=toBaryCoord(1,0) - (O_v,O_w) and then find (y_v,y_w) by computing (y_v,y_w) = toBaryCoord(0,1)-(O_v,O_w).
This computation requires calling toBaryCoord three times, but actually the coefficients are computed inside that routine every time, so you could modify it to compute at once all six values.
The value of your function vp can be computed as follows. I will use f instead of v because we are using v for a baricenter coordinate. Hence in the following I mean f(x,y) = vp, fa = va, fb = vb, fc = vc.
You have:
f(v,w) = fa + (fb-fa)*v + (fc-fa)*w
i.e.
f(x,y) = fa + (fb-fa) (O_v + x_v * x + y_v * y) + (fc-fa) (O_w + x_w * x + y_w * y)
where (x,y) are the coordinates of your point p. You can check the validity of this equation by inserting the coordinates of the three vertices a, b, c and verify that you obtain the three values fa, fb and fc. Remember that the barycenter coordinates of a are (0,0) hence O_v + x_v * a_x + y_v * a_y = 0 and so on... (a_x and a_y are the x,y coordinates of the point a).
If you let
q = fa + (fb_fa)*O_v + (fc-fa)*O_w
fx = (fb-fa)*x_v + (fc-fa) * x_w
fy = (fb-fa)*y_v + (fc-fa) * y_w
you get
f(x,y) = q + fx*x + fy * y
Notice that q, fx and fy can be computed once from a,b,c,fa,fb,fc and you can reuse them if you only change the coordinates (x,y) of the point p.
Now if f(x,y)>max, you can easily project (x,y) on the line where max is achieved. The coordinates of the projection are:
(x',y') = (x,y) - [(x,y) * (fx,fy) - max + q]/[(fx,fy) * (fx,fy)] (fx,fy)
Now. You would like to have the code. Well here is some pseudo-code:
toBarycoord(Vector2(0,0),a,b,c,O);
toBarycoord(Vector2(1,0),a,b,c,X);
toBarycoord(Vector2(0,1),a,b,c,Y);
X.sub(O); // X = X - O
Y.sub(O); // Y = Y - O
V = Vector2(fb-fa,fc-fa);
q = fa + V.dot(O); // q = fa + V*O
N = Vector2(V.dot(X),V.dot(Y)); // N = (V*X,V*Y)
// p is the point to be considered
f = q + N.dot(p); // f = q + N*p
if (f > max) {
Vector2 tmp;
tmp.set(N);
tmp.multiply((N.dot(p) - max + q)/(N.dot(N))); // scalar multiplication
p.sub(tmp);
}
if (f < min) {
Vector2 tmp;
tmp.set(N);
tmp.multiply((N.dot(p) - min + q)/(N.dot(N))); // scalar multiplication
p.sum(tmp);
}
We think of the problem as follows: The three points are interpreted as a triangle floating in 3D space with the value being the Z-axis and the cartesian coordinates mapped to the X- and Y- axes respectively.
Then the question is to find the gradient of the plane that is defined by the three points. The lines where the plane intersects with the z = min and z = max planes are the lines you want to restrict your points to.
If you have found a point p where v(p) > max or v(p) < min we need to go in the direction of the steepest slope (the gradient) until v(p + k * g) = max or min respectively. g is the direction of the gradient and k is the factor we need to find. The coordinates you are looking for (in the cartesian coordinates) are the corresponding components of p + k * g.
In order to determine g we calculate the orthonormal vector that is perpendicular to the plane that is determined by the three points using the cross product:
// input: px, py, pz,
// output: p2x, p2y
// local variables
var v1x, v1y, v1z, v2x, v2y, v2z, nx, ny, nz, tp, k,
// two vectors pointing from b to a and c respectively
v1x = ax - bx;
v1y = ay - by;
v1z = az - bz;
v2x = cx - bx;
v2y = cy - by;
v2z = cz - bz;
// the cross poduct
nx = v2y * v1z - v2z * v1y;
ny = v2z * v1x - v2x * v1z;
nz = v2x * v1y - v2y * v1x;
// using the right triangle altitude theorem
// we can calculate the vector that is perpendicular to n
// in our triangle we are looking for q where p is nz, and h is sqrt(nx*nx+ny*ny)
// the theorem says p*q = h^2 so p = h^2 / q - we use tp to disambiguate with the point p - we need to negate the value as it points into the opposite Z direction
tp = -(nx*nx + ny*ny) / nz;
// now our vector g = (nx, ny, tp) points into the direction of the steepest slope
// and thus is perpendicular to the bounding lines
// given a point p (px, py, pz) we can now calculate the nearest point p2 (p2x, p2y, p2z) where min <= v(p2z) <= max
if (pz > max){
// find k
k = (max - pz) / tp;
p2x = px + k * nx;
p2y = py + k * ny;
// proof: p2z = v = pz + k * tp = pz + ((max - pz) / tp) * tp = pz + max - pz = max
} else if (pz < min){
// find k
k = (min - pz) / tp;
p2x = px + k * nx;
p2y = py + k * ny;
} else {
// already fits
p2x = px;
p2y = py;
}
Note that obviously if the triangle is vertically oriented (in 2D it's not a triangle anymore actually), nz becomes zero and tp cannot be calculated. That's because there are no more two lines where the value is min or max respectively. For this case you will have to choose another value on the remaining line or point.

How do I find the intersection of a vector and the side of a triangle?

I have a triangle with given vertices ABC. Given a vector that starts from A and intersects side BC, how can I find the point of intersection, p?
See diagram:
Parametrize the line BC as B+s(C-B) with s going from 0 to 1. Do the same for the vector, i.e. as A + t(D-A), where D is any point along the vector, and the range of t is not limited.
Now denote the coordinates of the points as A.x, A.y and so on. You have to solve the equations
A.x + t(D.x - A.x) == B.x + s(C.x - B.x)
A.y + t(D.y - A.y) == B.y + s(C.y - B.y)
to determine s and t. Then p = B+s(C-B) where s is the solution of the equation. There might be an easier solution for triangles, but this should work!

Resources