/// <summary> /// Gets the distance from a point p to its projection on a segment</summary> /// <param name="seg">Segment</param> /// <param name="p">Point to project</param> /// <returns>Distance from point p to its projection on segment</returns> public static float DistanceToSegment(Seg2F seg, Vec2F p) { Vec2F projection = Project(seg, p); float d = Vec2F.Distance(p, projection); return(d); }
/// <summary> /// Picks the specified curve</summary> /// <param name="curve">Curve</param> /// <param name="p">Picking point</param> /// <param name="tolerance">Pick tolerance</param> /// <param name="hitPoint">Hit point</param> /// <returns>True if curve found; false otherwise</returns> public static bool Pick(BezierCurve2F curve, Vec2F p, float tolerance, ref Vec2F hitPoint) { Queue <BezierCurve2F> curves = new Queue <BezierCurve2F>(); curves.Enqueue(curve); float dMin = float.MaxValue; Vec2F closestPoint = new Vec2F(); while (curves.Count > 0) { BezierCurve2F current = curves.Dequeue(); // project p onto segment connecting curve endpoints Seg2F seg = new Seg2F(current.P1, current.P4); Vec2F projection = Seg2F.Project(seg, p); float d = Vec2F.Distance(p, projection); // reject - point not near enough to segment, expanded by curve "thickness" float flatness = current.Flatness; if (d - flatness > tolerance) { continue; } // accept - point within tolerance of curve if (flatness <= tolerance) { if (d < dMin) { dMin = d; closestPoint = projection; } } else { BezierCurve2F left, right; current.Subdivide(0.5f, out left, out right); curves.Enqueue(left); curves.Enqueue(right); } } if (dMin < tolerance) { hitPoint = closestPoint; return(true); } return(false); }
/// <summary> /// Constructs the circle containing 3 points</summary> /// <param name="p1">Point 1</param> /// <param name="p2">Point 2</param> /// <param name="p3">Point 3</param> public CircleF(Vec2F p1, Vec2F p2, Vec2F p3) { Vec2F o1 = Vec2F.Add(p1, p2); o1 *= 0.5f; Vec2F o2 = Vec2F.Add(p3, p2); o2 *= 0.5f; Vec2F d1 = Vec2F.Sub(p2, p1); d1 = d1.Perp; Vec2F d2 = Vec2F.Sub(p3, p2); d2 = d2.Perp; double t1 = 0; double t2 = 0; if (Ray2F.Intersect(new Ray2F(o1, d1), new Ray2F(o2, d2), ref t1, ref t2)) { Center = o1 + d1 * (float)t1; Radius = Vec2F.Distance(Center, p1); } else { Center = new Vec2F(float.PositiveInfinity, float.PositiveInfinity); Radius = float.PositiveInfinity; } }