public static double[] AnglesCrossLine(Point centre, double r, Point pt1, Point pt2) { Point t = Funcs2D.PointToLine(pt1, pt2, centre); if (Funcs2D.IsEqual(t, centre)) { double an = Funcs2D.LineAngle(pt1, pt2); return(new double[] { Funcs2D.PureRadianAngle(an + Math.PI), an }); } double z = Funcs2D.Distance(centre, t); double a = Funcs2D.LineAngle(centre, t); if (z.IsGreater(r)) { return(null); // mimo } if (z.IsEqual(r)) // tecna { return(new double[] { a }); } //secna double aa = Math.Acos(z / r); // uhel pulky tetivy return(new double[] { Funcs2D.PureRadianAngle(a + aa), Funcs2D.PureRadianAngle(a - aa) }); }
/// <summary> /// otestuje zda prislusny bot lezi na oblouku /// </summary> /// <param name="pt">testovany bod</param> /// <returns></returns> public bool IsPointOn(Point pt) { Circle2D?c = GetAngles(out double st, out double an); if (c == null) { return(false); } if (!Funcs2D.Distance(pt, c.Value.Center).IsEqual(Math.Abs(Radius))) { return(false); } st = Funcs2D.PureRadianAngle(st); double angle = Funcs2D.LineAngle(c.Value.Center, pt); if (an > 0) { an = st + an; return(angle.IsGreaterOrEqual(st) && angle.IsLesserOrEqual(an)); } else { an = st + an; return(angle.IsGreaterOrEqual(an) && angle.IsLesserOrEqual(st)); } }
/// <summary> /// kruznice urcena tremi body na obvodu /// </summary> /// <param name="pt1">prvni bod</param> /// <param name="pt2">druhy bod</param> /// <param name="pt3">treti bod</param> public Circle2D(Point pt1, Point pt2, Point pt3) { Radius = 0; Center = pt1; Point[] p = new Point[2]; Vector[] v = new Vector[2]; p[0].X = (pt1.X + pt2.X) / 2; p[0].Y = (pt1.Y + pt2.Y) / 2; p[1].X = (pt2.X + pt3.X) / 2; p[1].Y = (pt2.Y + pt3.Y) / 2; v[0].X = pt2.Y - pt1.Y; v[0].Y = -(pt2.X - pt1.X); v[1].X = pt3.Y - pt2.Y; v[1].Y = -(pt3.X - pt2.X); TwoLine2D.CrossStatus st = TwoLine2D.CrossStatus.Infinite; if (TwoLine2D.CrossAbs(p[0], st, v[0], st, p[1], st, v[1], st, out Center)) { Radius = Funcs2D.Distance(pt1, Center); } }
/// <summary> /// oblouk zadany stredem , pocatecnim bodem a vektorem ne kterem lezi kocovy bod /// </summary> /// <param name="center">stred</param> /// <param name="pt">pocatecni bod</param> /// <param name="vector">vektor na kterem lezi koncovy bod</param> /// <param name="shortangle">true = kratky oblouk (mezi nulou az 180 stupni), false = dlouhy oblouk (doplnek do 360 stupnu)</param> public Arc2D(Point center, Point pt, Vector vector, bool shortangle = true) { Radius = Funcs2D.Distance(center, pt); Begin = pt; double a = Funcs2D.Radian(Vector.AngleBetween(new Vector(1, 0), vector)); End = Circle2D.PointOn(center, Radius, a); if (!shortangle) { Radius *= -1; } a = Vector.AngleBetween(pt.Minus(center), vector); Clockwise = !(a > 0 && shortangle || a < 0 && !shortangle); }
/// <summary> /// kruznice zadana dvema body na obvodu a polomerem /// , pokud je polomer mensi nez polovina vzdalenosti bodu, umisti se stred kruznice do stredoveho bodu tvoriciho obema ridicimi body /// , stred kruznice se umisti do poloroviny urcene ridicimi body, podle znamenka polomeru /// </summary> /// <param name="pt1">prvni bod na obvodu</param> /// <param name="pt2">druhy bod na ovodu</param> /// <param name="r">polomer</param> public Circle2D(Point pt1, Point pt2, double r) { double d = Funcs2D.Distance(pt1, pt2) / 2; if (Math.Abs(r) <= d) { Radius = d; Center = new Point((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2); } else { Radius = Math.Abs(r); double v = Math.Sqrt(Math.Pow(Radius, 2) - Math.Pow(d, 2)); Center = Funcs2D.LineRelPtOffset(pt1, pt2, 0.5, r < 0 ? -v : v); } }
/// <summary> /// oblouk zadany stredem , pocatecnim bodem a uhlem /// </summary> /// <param name="center">stred</param> /// <param name="pt">pocatecni bod</param> /// <param name="angle">uhel v radianech , smer podle znamenka ( - = clockwise)</param> public Arc2D(Point center, Point pt, double angle) { Radius = Funcs2D.Distance(center, pt); Begin = pt; if (Math.Abs(angle) > Math.PI * 2) { angle = angle % (Math.PI * 2); } Clockwise = angle < 0; double a = Funcs2D.Radian(Vector.AngleBetween(new Vector(1, 0), pt.Minus(center))); a += angle; End = Circle2D.PointOn(center, Radius, a); if (Math.Abs(angle) > Math.PI) { Radius *= -1; } }
/// <summary> /// oblouk tvoreny dvema po sobe jdoucimi useckami a polomerem /// takzvane zaobleni rohu /// pokud je polomer zaporny vytvori se tzv. vykousnuti se stredem ve spolecnem bode /// objekt se nastavi na empty pokud jsou usecky rovnobezne nebo jedna z nich ma nulovou delku /// </summary> /// <param name="pt1">pocatecni bod prvni ridici usecky</param> /// <param name="pt2">spolecny bod ridicich usecek</param> /// <param name="pt3">konecny bod druhe ridici usecky</param> /// <param name="radius">polomer zaobleni, zaporny polomer provede vykousnuti</param> /// <param name="testPt">pokud se pocatecni nebo koncovy bod vypocita mimo usecku, objekt se nastavi na Empty</param> public Arc2D(Point pt1, Point pt2, Point pt3, double radius, bool testPt = false) { // zjistim smer offsetu double a = Vector.AngleBetween(pt2.Minus(pt1), pt3.Minus(pt2)); if (a > 0) { a = -Math.Abs(radius); Clockwise = false; } else { a = Math.Abs(radius); Clockwise = true; } // vypocitam prusecik offsetovanych primek Point[] p1 = Funcs2D.LineOffset(pt1, pt2, a); Point[] p2 = Funcs2D.LineOffset(pt2, pt3, a); if (p1 == null || p2 == null || !TwoLine2D.CrossRel(p1[0], p1[1], p2[0], p2[1], out Point rr)) { // tri body na jedne primce Begin = pt1; End = pt3; Radius = 0; return; } if (radius > 0) { if (testPt) { if (!TwoLine2D.TestRelOnLine(TwoLine2D.CrossStatus.And, rr.X) || !TwoLine2D.TestRelOnLine(TwoLine2D.CrossStatus.And, rr.Y)) { // body jsou mimo usecky Begin = pt1; End = pt3; Radius = 0; return; } } // koeficienty prenesu do puvodnich usecek a spocitam body Begin = Funcs2D.PointOnLine(pt1, pt2, rr.X); End = Funcs2D.PointOnLine(pt2, pt3, rr.Y); Radius = radius; } else { Radius = -radius; if (testPt) { if (Funcs2D.Distance(pt1, pt2) < Radius || Funcs2D.Distance(pt2, pt3) < Radius) { // body jsou mimo usecky Begin = pt1; End = pt3; Radius = 0; return; } } // bod na prvni primce ve vzdalenosti abs(radius) od spolecneho bodu Begin = Funcs2D.PointOnLineLen(pt2, pt1, Radius); // bod na druhe primce End = Funcs2D.PointOnLineLen(pt2, pt3, Radius); Clockwise = !Clockwise; } }
/// <summary> /// kruznice zadana stredem a bodem na obvodu /// </summary> /// <param name="center">stred</param> /// <param name="pt">bod na obvodu</param> public Circle2D(Point center, Point pt) { Radius = Funcs2D.Distance(center, pt); Center = center; }