private Point[] GetPositions(Point start, Point end, double[] lengths, Vector startTangent, Vector endTangent) { var lengthSum = lengths.Sum(); var dist = (end - start).Magnitude; BezierSpline spline = null; double relEps = 0.001; var startDir = startTangent.GetNormalized(); var endDir = endTangent.GetNormalized(); Point[] resPoints = null; int lengthSampleCount = (int)(lengthSum / lengths.Min()); #if DEBUG #region Time double startTime = Reporting.Seconds; double prevTime = startTime; double curTime; Action<string, bool> printTime = (message, fromStart) => { curTime = Reporting.Seconds; var lastTime = fromStart ? startTime : prevTime; Reporting.LogMessage("{0} = {1} [ms] at {2} [fps]", message, Math.Round((curTime - lastTime) * 1000, 2), Math.Round(1.0 / (curTime - lastTime), 2)); if (!fromStart) prevTime = curTime; }; #endregion Time #endif Func<double, double> func = (p) => { spline = new BezierSpline(start, start + startDir * p, end + endDir * p, end); #if DEBUG DebugGeo.Add(spline); #endif return spline.GetLength(lengthSampleCount * 2) - lengthSum; }; double param = 0; double eps = lengthSum * relEps; ; double minParam = (lengthSum - dist) / 2; double maxParam = Math.Sqrt(lengthSum * lengthSum - dist * dist); var success = MathUtils.SolveByBisection(func, minParam, maxParam, out param, eps); if (!success) { success = MathUtils.SolveByBisection(func, minParam / 2, maxParam * 2, out param, eps); if (!success) return null; } #if DEBUG printTime("SplinePreparation", false); #endif spline = new BezierSpline(start, start + startDir * param, end + endDir * param, end); resPoints = spline.GetResampledByDistance(lengths, true); #if DEBUG printTime("Resample", false); #endif #if DEBUG printTime("Finished", true); #endif return resPoints; }
private static IEnumerable<IGeoDraw> ToDrawableGeo_dyn(BezierSpline spline) { yield return new GeoSpline( spline.PosA.ToPointD(), spline.PosB.ToPointD(), spline.PosC.ToPointD(), spline.PosD.ToPointD(), ColorF.Green.SetAlpha(0.5f), 2, true); }