public static MinimumRadiusResult FindMinimumRadius(this ICurve curve) { var bound = curve.Domain(); int numOfRadius = 0; object radiusObject = null; object locationObject = null; object tObject = null; var hasRadius = curve.FindMinimumRadius(bound , ref numOfRadius , ref radiusObject , ref locationObject , ref tObject); if (hasRadius && numOfRadius > 0) { return(new MinimumRadiusResult (t: ((double[])tObject)[0] , radius: ((double[])radiusObject)[0] , location: ((MathPoint)((object[])locationObject)[0]).ToVector3())); } else { return(null); } }
public static PointParamWithRayProjection ClosestPointToRay(this ICurve curve, PointDirection3 ray, double tol = 1e-9) { var bound = curve.Domain(); int numOfRadius = 0; double[] radius = null; MathPoint location = null; var radiusResult = curve.FindMinimumRadius(); var domain = new RangeDouble(curve.Domain()); var tessTol = radiusResult.Radius / 10; var closestPointOnEdge = Vector3.Zero; for (var i = 0; i < 1; i++) { var tessPoints = Sequences .LinSpace(domain.Min, domain.Max, 100) .Select(curve.PointParamAt).ToList(); var edges = tessPoints.Buffer(2, 1).Where(buf => buf.Count == 2) .ToList(); var closestEdge = edges .Select(edge => new { edge, connection = MakeEdge(edge).ShortestEdgeJoining(ray, tol) }) .MinBy(o => o.connection.LengthSquared)[0]; var a = closestEdge.edge[0].T; var b = closestEdge.edge[1].T; domain = new RangeDouble(a, b); tessTol = tessTol / 10; } Func <Vector3, Vector3> projectOnRay = p => (p - ray.Point).ProjectOn(ray.Direction) + ray.Point; var solver = new BrentSearch(t => { var p = curve.PointAt(t); var proj = projectOnRay(p); return((p - proj).LengthSquared()); }, domain.Min, domain.Max); solver.Minimize(); var minT = solver.Solution; var pointParam = curve.PointParamAt(minT); return(new PointParamWithRayProjection(pointParam, projectOnRay(pointParam.Point))); }