Find center of a circle - c#

I need some c# code for the following:
I have two points (2D). The points are on a circle with radius r. I know the tangent angle in each of the points. I need to get hold of the circle mid point.
//Thomas
OK, I think I was a bit unclear. See image below. The point P1 is at the end of a line, the line has the angle At1. The point P2 is at the beginning of a line with the angle At2. I know the coordinates for P1 and P2. I also know the angles At1 and At2. A radius is formed between P1 and P2 and I need to know the center point Pc for the (invisible) circle the which is formed with P1, P2, At1 and At2. The points P1 and P2 can be anywhere in the coordiante system.
I know it's not c#, however I was hoping to come across someone who's solved this.
See image

If the points are not known to be most-far from one another on the circle, then there is an infinite amount of circles that they can be on.
Otherwise, it's simple:
Point pt1 = ...
Point pt2 = ...
Point mid = new Point((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);

First, check if the tangent angles are parallel. If they are, then all you need to do is find the midpoint between them (as they both lay along the circle's diameter) as per Yorye Nathan's solution.
If they're not parallel, then you can draw two lines perpendicular to the tangent angles starting from your known P1 and P2. If you solve the intersection of these two lines, then that intersection will be Pc.
I don't have the time right now to write up the full C# math and test it, but some pseudocode for you might be:
public Point CalculateCircleCentre(Point p1, Degrees tangent1, Point p2, Degrees tangent2)
{
if (AreAnglesParallel(tangent1, tangent2))
{
return Midpoint(p1, p2);
}
else
{
var line1 = new Line(p1, tangent1 + 90);
var line2 = new Line(p2, tangent2 + 90);
var intersectionPoint = FindIntersection(line1, line2);
return intersectionPoint;
}
}

Assuming you have 2 points on a circle with coordinates (x1, y1), (x2, y2) and point (x3, y3) is the center of a circle with radius r all you need to do is to find x3 and y3. Solve this system:
(x3-x1)^2+(y3-y1)^2=r^2
(x3-x2)^2+(y3-y2)^2=r^2
expands to
x3*x3-2*x3*x1+x1*x1 + y3*y3-2*y3*y1+y1*y1 = r*r
x3*x3-2*x3*x2+x2*x2 + y3*y3-2*y3*y2+y2*y2 = r*r
2*x3*(x2-x1) + 2*y3*(y2-y1) + x1*x1 + x2*x2 + y1*y1 + y2*y2 = 0
You now can substitute x3 with this long expression and find y3
x3 = (2*y3*(y1-y2) - (x1*x1 + x2*x2 + y1*y1 + y2*y2)) / (2*(x2-x1))
After that you will know everything to find x3.

Related

How to calculate a point horizontaly projected to an angled line

We are using Unity C#. This image is a simplified 2D situation, in which we know the coordinates (x,y) of points p1 and p2.
We know the angle Theta, using this beauty
static float CalculateAngle(Vector3 p1, Vector3 p2)
{ return Quaternion.FromToRotation(Vector3.right, p1 - p2).eulerAngles.z; }
// The use of Vector3.right make zero degrees start at 3h00
// The values of z are irrelevant in this post, always zeroed.
Now a new point p3 shows up, imagine a screen touch, so we know it's coordinates (x,y). In essence, everything blue in the image, we know it's values.
The question is this: how to calculate a new p4 coordinates, in which
we know p3(x,y) coordinates
we don't know p4(x,y), except that:
p4.y has to be equal to p3.y
p4 is in line with p1 and p2
How to calculate the unknown p4.x, to have the full p4(x,y) coordinates, using Unity C#?
There may be easier solutions out there. The basic Math solution is as follows:
Calculate the linear function of p1 and p2 as mentioned here. An equation in the slope-intercept form is written as
y = mx + b
where m is the slope of the line and b is the y-intercept.
Insert P3's y into the form.
Solve x.
Example in C# for Unity:
Vector3 p1 = new Vector3(1f, 2f);
Vector3 p2 = new Vector3(2f, 3f);
Vector3 p3 = new Vector3(1000f, 5f);
Vector3 p4 = Vector3.zero;
float m = ((p2.y - p1.y) / (p2.x - p1.x));
float b = p1.y - (m * p1.x);
// x = ( y - b ) / m
p4.x = (p3.y - b) / m;
p4.y = p3.y;
print(p4); // (4.0, 5.0, 0.0) as expected
Linear functions are of the form y = mx + b, where m is the slope and b is the vertical shift. If P3 is a point with an xy values, then you can take the slope, the offset, and y and solve for x:
(y - b) / m = x
This is more of a general math question than a unity specific question; in the future, I'd suggest trying the stack exchange math site.
This will solve your problem, and it also works for p1,p2, and/or p3 with different depths:
Create a plane where Y=p3.y, and then raycast from p1->p2 to find where it intersects.
Plane plane = new Plane(Vector3.up, p3);
float enter;
Ray ray = new Ray(p1, p2-p1);
bool doesIntersect = plane.Raycast(ray, out enter);
if (doesIntersect) {
Vector3 p4 = ray.GetPoint(enter);
DoStuff(p4.x);
}
If you need to project along a non-horizontal direction, you'll need to use a different normal than Vector3.up.

Algorithm for rounding a corner between line and arc

I need an algorithm that can round a corner between a line and an arc. The start information that I have is P0-start point, P-corner point, P2-end point, R2-radius of the arc between P and P2 and R-radius of the rounded corner(on the second picture).
Output or wanted points are cross sections C0 and C2 and center point of the rounding circle-O
In my sketch BF is part of given segment (F is not known yet), C is center of given arc, B is point of rough conjugation. c is line, parallel to BF, |GF|=|GH| = r - radius of small arc.
To make smooth conjugation, tangent to small arc in point F should be collinear with BF direction, so GF is perpendicular to BF, and tangents to both arcs in point H should coincide - so radius-vectors CH and GH lie on the same line.
Let unit direction vector of BF segment is ud=(dx,dy), so unit normal is un=(-dy, dx). (Negate normal for arcs at another side of BF)
Center of small arc G has coordinates (where t is unknown parameter - length of BF)
G = B + ud * t + un * r
and distance GC is difference of arcs radii, so
|G - C| = |R - r|
or in coordinates:
(B.x + dx * t - dy * r - C.x)^2 + (B.y + dy * t + dx * r - C.y)^2 = (R - r)^2
Open parentheses, solve quadratic equation for unknown t. If solutions exist, choose right root, and you'll get coordinates of center of conjugation arc G and its ends
quick check1:
Line Y=5, big arc with R=5, we want small arc with r=2
B=(5,5)
ud=(-1,0)
un=(0,-1)
(5-t)^2 + (5-2-5)^2 = (5-2)^2
solution gives
t = 5 +/- Sqrt(5), the second root is valid
E = (5 - (5 - Sqrt(5)), 3) = (2.23, 3)
Resulting smooth arc is c-f
quick check2:
Line Y=5, big arc with R=5, we want small arc with r=2
B=(5,5)
big arc center (H here) = (1,2)
ud=(-1,0)
un=(0,-1)
(4-t)^2 + (5-2-2)^2 = (5-2)^2
solution gives
t = 4 +/- Sqrt(8), the second root is valid
E = (5 - (4 - Sqrt(8)), 3) = (3.83, 3)
Resulting smooth arc is F-G
(In both cases larger root corresponds to conjugation with complementary part of big arc)
There isn't enough specification to choose a unique arc. You need to figure out what endpoints you want. Then solve for the ellipse that is tangent to both of those points. See Wikipedia/ellipse for the equations. I recommend a math package (e.g. SciKit) to solve for you.

Making a Pen's LineCap go more into the drawn Line/Curve

Currently I have the following code:
AdjustableArrowCap arrow = new AdjustableArrowCap(10, 15, false);
penStateOutline.CustomEndCap = arrow;
And it draws this:
I have tried all day to make the arrow point to the ellipse itself rather than the center of it..
Update (I was wrong about the cap extending the line; it doesn't!)
To let the line and its cap end at the cirlce's outside you need to make the line shorter by the radius of the circle.
There are two approaches:
You can find a new endpoint that sits on the circle by calculating it, either with Pythagoras or by trigonometry. Then replace the endpoint, i.e. the circle's center, when drawing the line or curve by that new point.
Or put the other way round: You need to calculate a point on the circle as the new endpoint of the line.
It requires a little math, unless the line is horizontal or vertical...
This will work well for straight lines but for curves it may cause considerable changes in the shape, depending on how close the points get and how curved the shape is.
This may or may not be a problem.
To avoid it you can replace the curve points by a series of line points that are close enough to look like a curve when drawn. From the list of points we subtract all those that do not lie inside the circle.
This sounds more complicated than it is as there is a nice class called GraphicsPath that will allow you to add a curve and then flatten it. The result is a more or less large number of points. The same class also allows you to determine whether a point lies inside a shape, i.e. our case inside the circle.
To implement the latter approach, here is a routine that transforms a list of curve points to a list of line points that will end close to the circle..:
void FlattenCurveOutside(List<Point> points, float radius)//, int count)
{
using (GraphicsPath gp = new GraphicsPath())
using (GraphicsPath gpc = new GraphicsPath())
{
// firt create a path that looks like our circle:
PointF l = points.Last();
gpc.AddEllipse(l.X - radius, l.Y - radius, radius * 2, radius* 2);
// next one that holds the curve:
gp.AddCurve(points.ToArray());
// now we flatten it to a not too large number of line segments:
Matrix m = new Matrix(); // dummy matrix
gp.Flatten(m, 0.75f); // <== play with this param!!
// now we test the pathpoints from bach to front until we have left the circle:
int k = -1;
for (int i = gp.PathPoints.Length - 1; i >= 0; i--)
{
if ( !gpc.IsVisible(gp.PathPoints[i])) k = i;
if (k > 0) break;
}
// now we know how many pathpoints we want to retain:
points.Clear();
for (int i = 1; i <= k; i++)
points.Add(Point.Round(gp.PathPoints[i]));
}
}
Note that when the last part of the curve is too straight the result may look a little jagged..
Update 2
To implement the former approach here is a function that returns a PointF on a circle of radius r and a line connecting a Point b with the circle center c:
PointF Intersect(Point c, Point a, int rad)
{
float dx = c.X - a.X;
float dy = c.Y - a.Y;
var radians = Math.Atan2(dy, dx);
var angle = 180 - radians * (180 / Math.PI);
float alpha = (float)(angle * Math.PI / 180f);
float ry = (float)(Math.Sin(alpha) * rad );
float rx = (float)(Math.Cos(alpha) * rad );
return new PointF(c.X + rx, c.Y - ry);
}
The result thankfully looks rather similar:
The math can be simplified a little..
To apply it you can get the new endpoint and replace the old one:
PointF I = Intersect(c, b, r);
points2[points2.Count - 1] = Point.Round(I);
Thank you so much to #TaW for helping.
Unfortunately the answer he provided did not match my stupid OCD..
You made me think about the problem from a different perspective and I now have found a solution that I'll share if anyone else needs, note that the solution is not perfect.
public static Point ClosestPointOnCircle(int rad, PointF circle, PointF other)
{
if (other.X == circle.X && other.Y == circle.Y) // dealing with division by 0
other.Y--;
return new Point((int)Math.Floor(circle.X + rad * ((other.X - circle.X) / (Math.Sqrt(Math.Pow(other.X - circle.X, 2) + Math.Pow(other.Y - circle.Y, 2))))), (int)Math.Floor(circle.Y + rad * ((other.Y - circle.Y) / (Math.Sqrt(Math.Pow(other.X - circle.X, 2) + Math.Pow(other.Y - circle.Y, 2))))));
}
What the code does is return a point on the circle that is the closest to the another point, then, I used the curve middle point as the other point to change the end point of the curve.
Then I used the arrow cap as normal and got this:image
Which is good enough for my project.

Calculate a specific curve with specific rotation, c#

I am trying to code for a game I am working on a specific curve with a specific rotation. I am not a great mathematician... At all... Tried searching for solutions for a few hours, but I'm affraid I do not find any solution.
So, a small picture to illustrate first:
This is an eighth of a circle, radius of 9, beggining is (0,0)
The end is now at about 6.364, -2.636. But I need this same curve, with a 45° direction at the end, but ending at aexactly 6.0,-3.0.
Could any of you show me how to do this? I need to be able to calculate precisly any point on this curve & its exact length. I would suppose using some kind of eliptical math could be a solution? I admit my math class are reaaaly far now and have now good clue for now...
Thank for any possible help
I think I found a quadratic curve which sastisfies your requirement:
f(x) = -1/12 x^2 + 9
Copy the following into https://www.desmos.com/calculator to see it:
-\frac{1}{12}x^2+9
f'(x) would be -1/6x, so when x=6, the derivative would be -1, which corresponds to a -45° inclination. There are probably infinite curves that satisfy your requirement but if my calculus isn't too rusty this is one of them.
I tried to fit an ellipse with foci starting at y=6 here and starting at y=9 here to your points but the slope doesn't look like 45°.
Also starting at any height k, here doesn't seem to work.
I don't think you've fully understood the question I asked in the comments about the "inclination" angle. So I will give a general case solution, where you have an explicit tangent vector for the end of the curve. (You can calculate this using the inclination angle; if we clarify what you mean by it then I will be happy to edit with a formula to calculate the tangent vector if necessary)
Let's draw a diagram of how the setup can look:
(Not 100% accurate)
A and B are your fixed points. T is the unit tangent vector. r and C are the radius and center of the arc we need to calculate.
The angle θ is given by the angle between BA and T minus π/2 radians (90 degrees). We can calculate it using the dot product:
The (signed) distance from the center of AB to C is given by:
Note that this is negative for the case on the right, and positive for the left. The radius is given by:
(You can simplify by substituting and using a cosine addition rule, but I prefer to keep things in terms of variables in the diagram). To obtain the point C, we need the perpendicular vector to AB (call it n):
Now that we have the radius and center of the circular arc, we still need to determine which direction we are moving in, i.e. whether we are moving clockwise or anti-clockwise when going from A to B. This is a simple test, using the cross-product:
If this is negative, then T is as in the diagram, and we need to move clockwise, and vice versa. The length of the arc l, and the angular displacement γ when we move by a distance x along the arc:
Nearly there! Just one more step - we need to work out how to rotate the point A by angle γ around point C, to get the point we want (call it D):
(Adapted from this Wikipedia page)
Now for some code, in case the above was confusing (it probably was!):
public Vector2 getPointOnArc(Vector2 A, Vector2 B, Vector2 T, double x)
{
// calculate preliminaries
Vector2 BA = B - A;
double d = BA.Length();
double theta = Math.Acos(Vector2.DotProduct(BA, T) / d) - Math.PI * 0.5;
// calculate radius
double r = d / (2.0 * Math.Cos(theta));
// calculate center
Vector2 n = new Vector2(BA.y, -BA.x);
Vector2 C = 0.5 * (A + B + n * Math.Tan(theta));
// calculate displacement angle from point A
double l = (Math.PI - 2.0 * theta) * r;
double gamma = (2.0 * Math.PI * x) / l;
// sign change as discussed
double cross = T.x * BA.y - T.y * BA.x;
if (cross < 0.0) gamma = -gamma;
// finally return the point we want
Vector2 disp = A - C;
double c_g = Math.Cos(gamma), s_g = Math.Sin(gamma);
return new Vector2(disp.X * c_g + disp.Y * s_g + C.X,
disp.Y * c_g - disp.X * s_g + C.Y);
}

Finding unkown point (x,y) given 2 points and distance in c#

i just get to the point and describe my problem .
Given a square not parallel to the axis !
i have (x1,y1) and (x2,y2) and the distance beetween them dx(width/height of the square)
i need to find the point (x,y) describe in the photo
(cant upload photo)
link to the image : the problem photo
first i tried the equation (x-x1)^2 + (y-y1)^2 = dx^2
(x-x2(^2 + (y-y2)^2 = 2 dx^2
but i cant manage to solve this equation when i try to code it ,
anyone have any idea's how to solve the problem in code or another equation or solution to find the point ?.
*i using c# 4,0
Very simple.
var dx = x2 - x1;
var dy = y2 - y1;
var rotatedDx = dy;
var rotatedDy = -dx;
x = x1 + rotatedDx;
y = y1 + rotatedDy;
Basically, you compute vector P1 -> P2 and rotate it by 90 degrees.
You can solve it using complex numbers by representing the points on an Argand diagram. (I think)
Since its a square, the sides are equal and 90degrees apart you can do this. (Refer to dropbox picture)
https://www.dropbox.com/s/ymimimgkuzhkcub/IMAG3818.jpg?dl=0
A is point (x1, y1) with value x1 + (y1)i
B is x2 + (y2)i
P and Q are the locations of the 2 possible places (x, y) can be and they are x + yi. Solve the 2 equation in the picture for values of x and y.

Categories

Resources