I have a ellipse with center point is at origin(0,0)
double dHalfwidthEllipse = 10;
double dHalfheightEllipse = 20;
double dAngle = 30;//Its in degree
PointF ptfPoint = new PointF();//To be found
PointF ptfOrigin = new PointF(0, 0);//Origin
Angle of point with respect to origin = 30 degree;
How to get the point now given the above values using C#?
See http://www.mathopenref.com/coordparamellipse.html
The parametric equation for an ellipse with center point at the origin, half width a and half height b is
x(t) = a cos t,
y(t) = b sin t
If you simply wish to draw an ellipse, given
double dHalfwidthEllipse = 10; // a
double dHalfheightEllipse = 20; // b
PointF ptfOrigin = new PointF(0, 0); // Origin
all you need is
PointF ptfPoint =
new PointF(ptfOrigin.X + dHalfwidthEllipse * Math.Cos(t * Math.Pi/180.0),
ptfOrigin.Y + dHalfheightEllipse * Math.Sin(t * Math.Pi/180.0) );
with t varying between -180 and 180 degrees.
However, as #Sebastian points out, if you wish to compute the exact intersection with a line through the center with angle theta, it gets a bit more complicated, since we need to find a t that corresponds to theta:
y(t)/x(t) = tan θ
b sin t / (a cos t) = tan θ
b/a tan t = tan θ
t= arctan(a tan θ / b) + n * π
So if we add
double dAngle = 30; // theta, between -90 and 90 degrees
We can compute t and ptfPoint:
double t = Math.Atan( dHalfwidthEllipse * Math.Tan( dAngle * Math.Pi/180.0 )
/ dHalfheightEllipse);
PointF ptfPoint =
new PointF(ptfOrigin.X + dHalfwidthEllipse * Math.Cos(t),
ptfOrigin.Y + dHalfheightEllipse * Math.Sin(t) );
This works fine for the area around the positive x axis.
For theta between 90 and 180 degrees, add π:
double t = Math.Atan( dHalfwidthEllipse * Math.Tan( dAngle * Math.Pi/180.0 )
/ dHalfheightEllipse) + Math.Pi;
For theta between -180 and -90 degrees, subtract π:
double t = Math.Atan( dHalfwidthEllipse * Math.Tan( dAngle * Math.Pi/180.0 )
/ dHalfheightEllipse) - Math.Pi;
As you get close to the y axis, x(t) approaches zero and the above calculation divides by zero, but there you can use the opposite:
x(t)/y(t) = tan (90 - θ)
a cos t / (b sin t) = tan (90 - θ)
a/b tan t = tan (90 - θ)
t = arctan ( b tan (90 - θ) / a ) + n * π
Related
I calculate the angles of a triangle, and I don't understand why I get a negative angle for some acute angle. For example:
var sin = Math.Sin(4.45);
var radians = Math.Atan(sin);
var angle = radians * (180 / Math.PI);
it return sin = -0.965 and angle = -44.
When scientific calculator show sin = 0.0775
My triangle has such lengths 6.22, 6.07 and 1.4 then there isn't option to had negative angle.
Math.Sin operates on radians. You need to convert degrees into radians.
To convert degrees to radians multiply the angle by 𝜋/180:
var sin = Math.Sin(4.45*Math.PI/180);
// output 0.07758909147106598
And the rest of your code should remain the same.
Note: if you just want to convert an angle in degrees to angle in radians you can use the formula above:
var degrees = 4.45;
var radians = degrees * Math.PI/180;
Let's compute angles of the triangle with a help of Law of cosines:
a**2 + b**2 - 2 * a * b * cos(gamma) == c**2
so
gamma = acos((a * a + b * b - c * c) / (2 * a * b))
beta = acos((a * a + c * c - b * b) / (2 * a * c))
alpha = acos((c * c + b * b - a * a) / (2 * c * b))
now put triangle lengths
a = 6.22
b = 6.07
c = 1.40
into formulae above and you'll get angles (in radians, if you use c# Math.Acos)
alpha = 1.5639 = 89.6 degrees
beta = 1.3506 = 77.4 degrees
gamma = 0.2270 = 13.0 degrees
------------------------------
180.0 degrees (let's check ourselves)
Another check is Law of sines
a / sin(alpha) == b / sin(beta) == c / sin(gamma) == 6.2201
I have a circle and want to draw a line inside that circle from the center (50|50) to the edge of the circle through the point i clicked on.
To test things, I already added this to my Circle.MouseDown event which draws the line from the center to the point I clicked on:
var PosX2 = e.GetPosition(MyCircle).X;
var PosY2 = e.GetPosition(MyCircle).Y;
CircleLine.X1 = 50;
CircleLine.Y1 = 50;
CircleLine.X2 = PosX2;
CircleLine.Y2 = PosY2;
What do I need to add to "stretch" my line to the edge of the Circle?
Think of it as a problem of lengthening a vector.
Suppose that you are given a circle with center (a,b) and radius r and that the point (c,d) lies in the circle at a point other than the center.
Then, the vector from (a,b) to (c,d) is (c-a, d-b). Its length is
L = sqrt((c-a)^2 + (d-b)^2)
But then the vector r/L * (c-a,d-b) has length r and points in the same direction as the ray from (a,b) to (c,d). Simply translate this vector by the center, and you get the desired point on the circle:
(a + r/L * (c-a), b + r/L * (d-b))
Just connect the center with the above point.
Johns comment got me the right answer, thank you!
I just wanted to post the solution:
double X1 = 75;
double Y1 = 75;
double X2 = e.GetPosition(CircleButtonCanvas).X;
double Y2 = e.GetPosition(CircleButtonCanvas).Y;
double startPoint = 17;
double endPoint = 48;
double xDiff = X2 - X1;
double yDiff = Y2 - Y1;
double Angle = Math.Atan2(yDiff, xDiff) * (180 / Math.PI);
CircleLine.X1 = 75 + (endPoint* Math.Cos(Angle * (Math.PI / 180)));
CircleLine.X2 = 75 + (startPoint * Math.Cos(Angle* (Math.PI / 180)));
CircleLine.Y1 = 75 + (endPoint * Math.Sin(Angle* (Math.PI / 180)));
CircleLine.Y2 = 75 + (startPoint * Math.Sin(Angle* (Math.PI / 180)));
With 75|75 beeing the center of my circle
I have locations of three points along the circle. pt1(x1, y1,z1), pt2(x2, y2, z2), pt3(x3, y3,z3). and want to find the radius of the circle. Already I have a function to compute radius in 2d space, which I am copying it here
public static double ComputeRadius(Location a, Location b, Location c)
{
double x1 = a.x;
double y1 = a.y;
double x2 = b.x;
double y2 = b.y;
double x3 = c.x;
double y3 = c.y;
double mr = (double)((y2 - y1) / (x2 - x1));
double mt = (double)((y3 - y2) / (x3 - x2));
double xc = (double)((mr * mt * (y3 - y1) + mr * (x2 + x3) - mt * (x1 + x2)) / (2 * (mr - mt)));
double yc = (double)((-1 / mr) * (xc - (x1 + x2) / 2) + (y1 + y2) / 2);
double d = (xc - x1) * (xc - x1) + (yc - y1) * (yc - y1);
return Math.Sqrt(d);
}
If you know the order of points pt1,pt2,pt3 along the circle then you can use graphical method:
cast normal axises from middle of each line segment in the plane of circle
your circle plane is defined by your 3 points. so the normal vector is
n = (pt2-pt1) x (pt3-pt2)
where the x is cross product so you have 2 lines (pt1,pt2) and (pt2,pt3) in black. The mid points are easy
p0=0.5*(pt1+pt2)
p1=0.5*(pt2+pt3)
the axis directions can be obtained also by cross product
dp0=(pt2-pt1) x n
dp1=(pt3-pt2) x n
so you got 2 axises:
pnt0(t)=p0+dp0*t
pnt1(u)=p1+dp1*u
Where t,u are scalar parameters t,u=(-inf,+inf) it is just position in axis from the starting mid point ...
the intersection is center of circle
So find the intersection of 2 axises and call it pt0
compute distance between center and any of your points
r=|pt1-pt0|
Sorry the image is for any curve (too lazy to repaint for circle as it is almost the same). If you do not know the order of points then the 2 points that are most distant to each other are the outer points ... In case they are equidistant the order does not matter any is OK
I am having some trouble trying to implement drawing an arc. Basically it's supposed to be drawn exactly like how you can draw a 3 point arc in AutoCAD. I can get the arc to draw with start and end angles from from -180 degrees to 360, but if I try to go more than -180, the arc flips around to +180 degrees. My problem is that I need the arc to continue when the angle passes -180. I have everything right in the code (I think) except for calculating the start and end angles. Thanks in advance for any help. Here is my code:
private void DrawArc()
{
//fyi linept is of type List<Point3D>();
Point3D currentPoint = (Point3D)GetPoints(e);
double rad;
Point3D center = GetCenterOfCircle(linept.ElementAt(0), linept.ElementAt(1), currentPoint, out rad);
PieSliceVisual3D circle = new PieSliceVisual3D();
circle.Center = center;
circle.OuterRadius = rad;
circle.InnerRadius = circle.OuterRadius + 3;
circle.StartAngle = (Math.Atan2(linept.ElementAt(0).Y - center.Y, linept.ElementAt(0).X - center.X) * 180 / Math.PI);
circle.EndAngle = (Math.Atan2(currentPoint.Y - center.Y, currentPoint.X - center.X) * 180 / Math.PI);
//I've also tried these next 4 lines to no avail
double startAngle = (Math.Atan2(linept.ElementAt(0).Y - center.Y, linept.ElementAt(0).X - center.X) * 180 / Math.PI);
circle.StartAngle = (startAngle > 0.0 ? startAngle : (360.0 + startAngle));
double endAngle = (Math.Atan2(currentPoint.Y - center.Y, currentPoint.X - center.X) * 180 / Math.PI);
circle.EndAngle = (endAngle > 0.0 ? endAngle : (360.0 + endAngle));
}
I need to draw an arc using GraphicsPath and having initial, median and final points. The arc has to pass on them.
I tried .DrawCurve and .DrawBezier but the result isn't exactly an arc.
What can I do?
SOLUTION:
After a couple of hours of code writing I managed to draw what I wanted with this algorithm (give 3 Point a,b,c and a GraphicsPath path):
double d = 2 * (a.X - c.X) * (c.Y - b.Y) + 2 * (b.X - c.X) * (a.Y - c.Y);
double m1 = (Math.Pow(a.X, 2) - Math.Pow(c.X, 2) + Math.Pow(a.Y, 2) - Math.Pow(c.Y, 2));
double m2 = (Math.Pow(c.X, 2) - Math.Pow(b.X, 2) + Math.Pow(c.Y, 2) - Math.Pow(b.Y, 2));
double nx = m1 * (c.Y - b.Y) + m2 * (c.Y - a.Y);
double ny = m1 * (b.X - c.X) + m2 * (a.X - c.X);
double cx = nx / d;
double cy = ny / d;
double dx = cx - a.X;
double dy = cy - a.Y;
double distance = Math.Sqrt(dx * dx + dy * dy);
Vector va = new Vector(a.X - cx, a.Y - cy);
Vector vb = new Vector(b.X - cx, b.Y - cy);
Vector vc = new Vector(c.X - cx, c.Y - cy);
Vector xaxis = new Vector(1, 0);
float startAngle = (float)Vector.AngleBetween(xaxis, va);
float sweepAngle = (float)(Vector.AngleBetween(va, vb) + Vector.AngleBetween(vb, vc));
path.AddArc(
(float)(cx - distance), (float)(cy - distance),
(float)(distance * 2), (float)(distance * 2),
startAngle, sweepAngle);
I would use DrawArc() as suggested by ANC_Michael. To find an arc that passes through 3 points you want to calculate the circumcircle of the triangle formed by the points.
Once you have the circumcircle calculate a bounding box for the circle to use with DrawArc using the min/max dimensions (center +/- radius). Now calculate your start and stop angles by translating the points so that the circumcircle is centered on the origin (translate by -circumcenter) and take the dot-product of the normalized start and end vectors with the X-axis:
double startAngle = Math.Acos(VectorToLeftPoint.Dot(XAxis));
double stopAngle = Math.Acos(VectorToRightPoint.Dot(XAxis));
Note that DrawArc expects angles clockwise from the X-axis so you should add Math.PI if the calculated vector is above the x-axis. That should be enough information to call DrawArc().
Edit: This method will find a circular arc and not necessarily the 'best fit' arc depending on your expected endpoint behavior.
Have you tried the DrawArc method and seeing if u can manipulate your 3 points somehow?
maybe
Pen blackPen= new Pen(Color.Black, 3);
// Create rectangle to bound ellipse.
Rectangle rect = new Rectangle(initial x, initial y, final x, median y);
// Create start and sweep angles on ellipse.
float startAngle = 0F;
float sweepAngle = 270.0F;
// Draw arc to screen.
e.Graphics.DrawArc(blackPen, rect, startAngle, sweepAngle);
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.drawarc%28VS.71%29.aspx