/// <summary> /// Gets a functional values in defined y position. /// </summary> /// <param name="start">The start point of the segment.</param> /// <param name="y">The y position.</param> /// <param name="global">True, if y and returned x value is are global space, false, if y and x are related to the start point.</param> /// <param name="tolerance">Tolerance</param> /// <returns>A values related to the y position.</returns> public override double[] GetValueByY(ref Point start, double y, bool global, double tolerance = 0) { Refresh(ref start); if (!global) { y += start.Y; } if (Comparators.InIntervalBoth(start.Y, EndPoint.Y, y, tolerance)) { // y = ax^2 + bx + c // ax^2 + bx + (c - y) = 0; var cc = c - y; var discr = (b * b) - 4 * a * cc; if (discr.IsGreater(0, 1e-5) && !a.IsZero()) { var x1 = (-b + Math.Sqrt(discr)) / (2 * a); var x2 = (-b - Math.Sqrt(discr)) / (2 * a); if (Comparators.InIntervalBoth(start.X, EndPoint.X, x1, tolerance) && Comparators.InIntervalBoth(start.X, EndPoint.X, x2, tolerance)) { return(new double[] { global?x1 : x1 - start.X, global ? x2 : x2 - start.X, }); } else if (Comparators.InIntervalBoth(start.X, EndPoint.X, x1, tolerance)) { return(new double[] { global?x1 : x1 - start.X }); } else if (Comparators.InIntervalBoth(start.X, EndPoint.X, x2, tolerance)) { return(new double[] { global?x2 : x2 - start.X }); } } } return(new double[0]); }
/// <summary> /// Gets a functional values in defined y position. /// </summary> /// <param name="start">The start point of the segment.</param> /// <param name="y">The y position.</param> /// <param name="global">True, if y and returned x value is are global space, false, if y and x are related to the start point.</param> /// <param name="tolerance">Tolerance</param> /// <returns>A values related to the y position.</returns> public override double[] GetValueByY(ref Point start, double y, bool global, double tolerance = 0) { if (!global) { y += start.Y; } var bounds = GetBounds(ref start); if (Comparators.InIntervalBoth(bounds.Top, bounds.Bottom, y, tolerance)) { var radius = GetRadius(ref start); var centre = GetCentre(ref start); y -= centre.Y; var x = Math.Sqrt(radius * radius - y * y); var c1 = Comparators.InIntervalBoth(bounds.Left, bounds.Right, centre.X + x, tolerance); var c2 = Comparators.InIntervalBoth(bounds.Left, bounds.Right, centre.X - x, tolerance); if (c1 && c2) { return(new double[] { global?centre.X + x : centre.X + x - start.X, global ? centre.X - x : centre.X - x - start.X, }); } else if (c1) { return(new double[] { global?centre.X + x : centre.X + x - start.X }); } else if (c2) { return(new double[] { global?centre.X - x : centre.X - x - start.X }); } } return(new double[0]); }
/// <summary> /// Gets a functional values in defined x position of the CircularArcSegment. /// </summary> /// <param name="start">The start point of the circular arc segment.</param> /// <param name="x">The x position.</param> /// <param name="global">True, if x and returned y value is are global space, false, if x and y are related to the start point.</param> /// <param name="tolerance">Tolerance</param> /// <returns>A values related to the x position.</returns> public override double[] GetValueByX(ref Point start, double x, bool global, double tolerance = 0) { if (!global) { x += start.X; } var bounds = GetBounds(ref start); if (Comparators.InIntervalBoth(bounds.Left, bounds.Right, x, tolerance)) { var radius = GetRadius(ref start); var centre = GetCentre(ref start); x -= centre.X; var y = Math.Sqrt(radius * radius - x * x); var c1 = Comparators.InIntervalBoth(bounds.Top, bounds.Bottom, centre.Y + y, tolerance); var c2 = Comparators.InIntervalBoth(bounds.Top, bounds.Bottom, centre.Y - y, tolerance); if (c1 && c2) { return(new double[] { global?centre.Y + y : centre.Y + y - start.Y, global ? centre.Y - y : centre.Y - y - start.Y, }); } else if (c1) { return(new double[] { global?centre.Y + y : centre.Y + y - start.Y, }); } else if (c2) { return(new double[] { global?centre.Y - y : centre.Y - y - start.Y, }); } } return(new double[0]); }
/// <summary> /// Gets a functional values in defined x position of the ParabolicArcSegment. /// </summary> /// <param name="start">The start point of the parabolic arc segment.</param> /// <param name="x">The x position.</param> /// <param name="global">True, if x and returned y value is are global space, false, if x and y are related to the start point.</param> /// <param name="tolerance">Tolerance</param> /// <returns>A values related to the x position.</returns> public override double[] GetValueByX(ref Point start, double x, bool global, double tolerance = 0) { Refresh(ref start); if (!global) { x += start.X; } if (Comparators.InIntervalBoth(start.X, EndPoint.X, x, tolerance)) { // y = ax^2 + bx + c var y = a * x * x + b * x + c; if (!global) { y -= start.Y; } return(new double[] { y }); } return(new double[0]); }
/// <summary> /// Calculates relative position on segment by given x position. /// </summary> /// <param name="start">The start point of the segment.</param> /// <param name="x">The x position.</param> /// <param name="global">True, if x and returned y value is are global space, false, if x and y are related to the start point.</param> /// <returns>The relative position.</returns> public override double[] GetRelativePosition(ref Point start, double x, bool global, double tolerance = 0) { if (!global) { x += start.X; } var radius = GetRadius(ref start); var centre = GetCentre(ref start); if (Comparators.InIntervalBoth(centre.X - radius, centre.X + radius, x, tolerance)) { var xx = x - centre.X; var y = (radius * radius - xx * xx).IsZero() ? 0 : Math.Sqrt(radius * radius - xx * xx); var cc = IsCounterClockwise(ref start); var angle = GetAngle(ref start); Func <Point, Point, double> getAngle = (s, p) => { var u1 = Point.Subtract(s, centre); var u2 = Point.Subtract(p, centre); var a = Vector.AngleBetween(u1, u2) * cc; if (a.IsZero()) { return(0); } return(a < 0 ? 360 + a : a); }; var px = new Point(x, centre.Y + y); var angle1 = getAngle(start, px); px.Y = centre.Y - y; var angle2 = getAngle(start, px); return(new double[] { angle1 / angle, angle2 / angle }); } return(new double[0]); }