Reputation: 11562
those are 2 example cases of what I need to solve, it is just finding the coordinate of D, given position of A, and the direction vector of red and green line
much help and hint appreciated, preferred in some code instead of math equation
Upvotes: 0
Views: 172
Reputation: 11562
thx for all the answer (will upvote them), I did the work on it myself, I will share my result :
and here is length of d, to solve the equation :
Upvotes: 0
Reputation: 29244
You know where A is and the angle θ it makes from vertical.
So specify the line though C called line(C)
above and the offset the line by R in order to get line(D)
above that goes through point D.
In C# code this is
Line line_C = Line.ThroughPointAtAngle(A, theta);
Line line_D = line_C.Offset(radius);
Now find the intersection of this line to the greater circle
Circle circle = new Circle(B, 2 * radius);
if (circle.Intersect(line_D, out Point D, alternate: false))
{
Console.WriteLine(D);
float d_BD = B.DistanceTo(D);
Console.WriteLine(d_BD);
}
else
{
Console.WriteLine("Does not intersect.");
}
This produces point D either above line(C)
or below line(C)
depending on the bool
argument alternate
.
The code example below produces the following output:
D=Point(-0.4846499,-1.94039)
|BD|=2
The source code is
using static Float;
static class Program
{
static void Main(string[] args)
{
float radius = 1;
Point A = new Point(-radius, 0);
Point B = new Point(0, 0);
float theta = deg(15);
Line line_C = Line.ThroughPointAtAngle(A, theta);
Line line_D = line_C.Offset(radius);
Circle circle = new Circle(B, 2 * radius);
if (circle.Intersect(line_D, out Point D, alternate: false))
{
Console.WriteLine($"D={D}");
float d_BD = B.DistanceTo(D);
Console.WriteLine($"|BD|={d_BD}");
}
else
{
Console.WriteLine("Does not intersect.");
}
}
}
Describes a point in cartesian space using two coordinates (x,y)
using static Float;
public readonly struct Point
{
readonly (float x, float y) data;
public Point(float x, float y)
{
this.data = (x, y);
}
public static Point Origin { get; } = new Point(0, 0);
public static Point FromTwoLines(Line line1, Line line2)
{
float x = line1.B * line2.C - line1.C * line2.B;
float y = line1.C * line2.A - line1.A * line2.C;
float w = line1.A * line2.B - line1.B * line2.A;
return new Point(x / w, y / w);
}
public float X => data.x;
public float Y => data.y;
public float SumSquares => data.x * data.x + data.y * data.y;
#region Algebra
public static Point Negate(Point a)
=> new Point(
-a.data.x,
-a.data.y);
public static Point Scale(float factor, Point a)
=> new Point(
factor * a.data.x,
factor * a.data.y);
public static Point Add(Point a, Point b)
=> new Point(
a.data.x + b.data.x,
a.data.y + b.data.y);
public static Point Subtract(Point a, Point b)
=> new Point(
a.data.x - b.data.x,
a.data.y - b.data.y);
public static float Dot(Point point, Line line)
=> line.A * point.data.x + line.B * point.data.y + line.C;
public static Point operator +(Point a, Point b) => Add(a, b);
public static Point operator -(Point a) => Negate(a);
public static Point operator -(Point a, Point b) => Subtract(a, b);
public static Point operator *(float f, Point a) => Scale(f, a);
public static Point operator *(Point a, float f) => Scale(f, a);
public static Point operator /(Point a, float d) => Scale(1 / d, a);
#endregion
#region Geometry
public Point Offset(float dx, float dy)
=> new Point(data.x + dx, data.y + dy);
public Point Offset(Vector2 delta) => Offset(delta.X, delta.Y);
public float DistanceTo(Point point)
=> sqrt(sqr(data.x - point.data.x) + sqr(data.y - point.data.y));
#endregion
#region Formatting
public string ToString(string formatting, IFormatProvider provider)
{
return $"Point({data.x.ToString(formatting, provider)},{data.y.ToString(formatting, provider)})";
}
public string ToString(string formatting)
=> ToString(formatting, null);
public override string ToString()
=> ToString("g");
#endregion
}
Describes a line in cartesian space using the coefficients (a,b,c)
such that the equation of the line is a x + b y + c = 0
using static Float;
public readonly struct Line
{
readonly (float a, float b, float c) data;
public Line(float a, float b, float c) : this()
{
data = (a, b, c);
}
public static Line AlongX { get; } = new Line(0, 1, 0);
public static Line AlongY { get; } = new Line(-1, 0, 0);
public static Line ThroughPointAtAngle(Point point, float angle)
{
return new Line(cos(angle), -sin(angle), point.Y * sin(angle) - point.X * cos(angle));
}
public static Line ThroughTwoPoints(Point point1, Point point2)
=> new Line(
point1.Y - point2.Y,
point2.X - point1.X,
point1.X * point2.Y - point1.Y * point2.X);
public float A => data.a;
public float B => data.b;
public float C => data.c;
#region Algebra
public static float Dot(Line line, Point point)
=> line.data.a * point.X + line.data.b * point.Y + line.data.c;
#endregion
#region Geometry
public Line ParallelThrough(Point point)
{
return new Line(data.a, data.b, -data.a * point.X - data.b * point.Y);
}
public Line PerpendicularThrough(Point point)
{
return new Line(data.b, -data.a, -data.b * point.X + data.a * point.Y);
}
public Line Offset(float amount)
=> new Line(data.a, data.b, data.c - amount * sqrt(sqr(data.a) + sqr(data.b)));
public Line Offset(float dx, float dy)
=> new Line(data.a, data.b, data.c + data.a * dx + data.b * dy);
public Line Offset(Vector2 delta) => Offset(delta.X, delta.Y);
public float DistanceTo(Point point)
=> Dot(this, point) / (data.a * data.a + data.b * data.b);
#endregion
#region Formatting
public string ToString(string formatting, IFormatProvider provider)
{
return $"Line({data.a.ToString(formatting, provider)}x+{data.b.ToString(formatting, provider)}y+{data.c.ToString(formatting, provider)}=0)";
}
public string ToString(string formatting)
=> ToString(formatting, null);
public override string ToString()
=> ToString("g");
#endregion
}
Describes a circle using the center and radius.
using static Float;
public readonly struct Circle
{
readonly (Point center, float radius) data;
public Circle(Point center, float radius)
{
this.data = (center, radius);
}
public static Circle FromTwoPoints(Point point1, Point point2)
{
float radius = point1.DistanceTo(point2) / 2;
Point center = (point1 + point2) / 2;
return new Circle(center, radius);
}
public static Circle FromThreePoints(Point point1, Point point2, Point point3)
{
float k_1 = point1.SumSquares / 2;
float k_2 = point2.SumSquares / 2;
float k_3 = point3.SumSquares / 2;
float dx_12 = point2.X - point1.X;
float dy_12 = point2.Y - point1.Y;
float dx_23 = point3.X - point2.X;
float dy_23 = point3.Y - point2.Y;
float det = dx_12 * dy_23 - dx_23 * dy_12;
Point center = new Point(
(dy_12 * (k_2 - k_3) + dy_23 * (k_2 - k_1)) / det,
(dx_12 * (k_3 - k_2) + dx_23 * (k_1 - k_2)) / det);
float radius = center.DistanceTo(point1);
return new Circle(center, radius);
}
public Point Center => data.center;
public float Radius => data.radius;
#region Geometry
public float DistanceTo(Point point)
=> data.center.DistanceTo(point) - data.radius;
public float DistanceTo(Line line)
{
float d = line.DistanceTo(Center);
if (d > 0)
{
return d - data.radius;
}
else
{
return d + data.radius;
}
}
public bool Intersect(Line line, out Point point, bool alternate = false)
{
line = line.Offset(-Center.X, -Center.Y);
int sign = alternate ? -1 : 1;
float discr = sqr(line.A * data.radius) + sqr(line.B * data.radius) - sqr(line.C);
if (discr >= 0)
{
float d = sign * sqrt(discr);
float ab = line.A * line.A + line.B * line.B;
point = new Point((line.B * d - line.A * line.C) / ab, -(line.A * d + line.B * line.C) / ab);
point += Center;
return true;
}
else
{
float ab = line.A * line.A + line.B * line.B;
point = new Point((-line.A * line.C) / ab, -(+line.B * line.C) / ab);
point += Center;
return false;
}
}
#endregion
#region Formatting
public string ToString(string formatting, IFormatProvider provider)
{
return $"Circle({data.center.ToString(formatting, provider)},{data.radius.ToString(formatting, provider)})";
}
public string ToString(string formatting)
=> ToString(formatting, null);
public override string ToString()
=> ToString("g");
#endregion
}
Helper functions dealing with float
math which is lacking from System.Math
.
public static class Float
{
/// <summary>
/// A factor of π.
/// </summary>
/// <param name="x">The factor.</param>
public static float pi(float x) => (float)(Math.PI * x);
/// <summary>
/// Degree to Radian conversion
/// </summary>
/// <param name="x">The angle in degrees.</param>
/// <returns>Angle in radians</returns>
public static float deg(float x) => pi(x) / 180;
/// <summary>
/// Radian to Degree conversion
/// </summary>
/// <param name="x">The angle in radians.</param>
/// <returns>Angle in degrees</returns>
public static float rad(float x) => x * 180 / pi(1);
public static float sqr(float x) => x * x;
public static float sqrt(float x) => (float)Math.Sqrt(x);
public static float sin(float x) => (float)Math.Sin(x);
public static float cos(float x) => (float)Math.Cos(x);
}
Upvotes: 1
Reputation: 53578
As a hint: draw it out some more:
We can construct D by constructing the line segment AG, for which we know both the angle and length, because AC⟂AG, and the segment has length R.
We can then construct a line perpendicular to AG, through G, which gives us a chord on the blue circle, one endpoint of which is D. We know the distance from B to GD (because we know trigonometry) and we know that the distance BD is 2R (because that's a given). Pythagoras then trivially gives us D.
Upvotes: 2
Reputation: 80187
Having coordinates A,B,C, we can write two vector equations using scalar (dot) product:
AC.dot.DC = 0
DB.dot.DB = 4*R^2
The first one refers to perpendicularity between tangent to circle and radius to tangency point, the second one - just squared distance between circle centers.
In coordinates:
(cx-ax)*(cx-dx) + (cy-ay)*(cy-dy) = 0
(bx-dx)*(bx-dx) + (by-dy)*(by-dy) = 4*R^2
Solve this system for unknown dx, dy
- two solutions in general case.
If A and C are not known, as @Mike 'Pomax' Kamermans noticed:
Let
cr = sin(v) sr = cos(v)
cg = sin(w) sg = cos(w)
So
ax = bx + R * cr
ay = by + R * sr
and
dx = cx - R * cg
dy = cy + R * sg
Substituting expressions into the system above we have:
(dx+R*cg-bx-R*cr)*cg - (dy-R*sg-by-R*sr)*sg = 0
(bx-dx)*(bx-dx) + (by-dy)*(by-dy) = 4*R^2
Again - solve system for unknowns dx, dy
Upvotes: 2