PolylineHelper.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace HandyControl.Expression.Drawing;
  5. internal static class PolylineHelper
  6. {
  7. public static IEnumerable<PolylineData> GetWrappedPolylines(IList<PolylineData> lines,
  8. ref double startArcLength)
  9. {
  10. var count = 0;
  11. for (var i = 0; i < lines.Count; i++)
  12. {
  13. count = i;
  14. startArcLength -= lines[i].TotalLength;
  15. if (MathHelper.LessThanOrClose(startArcLength, 0.0)) break;
  16. }
  17. if (!MathHelper.LessThanOrClose(startArcLength, 0.0))
  18. throw new ArgumentOutOfRangeException(nameof(startArcLength));
  19. startArcLength += lines[count].TotalLength;
  20. return lines.Skip(count).Concat(lines.Take(count + 1));
  21. }
  22. public static void PathMarch(PolylineData polyline, double startArcLength, double cornerThreshold,
  23. Func<MarchLocation, double> stopCallback)
  24. {
  25. if (polyline == null) throw new ArgumentNullException(nameof(polyline));
  26. var count = polyline.Count;
  27. if (count <= 1) throw new ArgumentOutOfRangeException(nameof(polyline));
  28. var flag = false;
  29. var x = startArcLength;
  30. var before = 0.0;
  31. var index = 0;
  32. var num5 = Math.Cos(cornerThreshold * 3.1415926535897931 / 180.0);
  33. while (true)
  34. {
  35. var num6 = polyline.Lengths[index];
  36. if (!MathHelper.IsFiniteDouble(x)) return;
  37. if (MathHelper.IsVerySmall(x))
  38. {
  39. x = stopCallback(MarchLocation.Create(MarchStopReason.CompleteStep, index, before,
  40. num6 - before, x));
  41. flag = true;
  42. }
  43. else if (MathHelper.GreaterThan(x, 0.0))
  44. {
  45. if (MathHelper.LessThanOrClose(x + before, num6))
  46. {
  47. before += x;
  48. x = stopCallback(MarchLocation.Create(MarchStopReason.CompleteStep, index, before,
  49. num6 - before, 0.0));
  50. flag = true;
  51. }
  52. else if (index < count - 2)
  53. {
  54. index++;
  55. var num7 = num6 - before;
  56. x -= num7;
  57. before = 0.0;
  58. // ReSharper disable once CompareOfFloatsByEqualityOperator
  59. if (flag && num5 != 1.0 && polyline.Angles[index] > num5)
  60. {
  61. num6 = polyline.Lengths[index];
  62. x = stopCallback(MarchLocation.Create(MarchStopReason.CornerPoint, index, before,
  63. num6 - before, x));
  64. }
  65. }
  66. else
  67. {
  68. var num8 = num6 - before;
  69. x -= num8;
  70. num6 = polyline.Lengths[index];
  71. before = polyline.Lengths[index];
  72. x = stopCallback(MarchLocation.Create(MarchStopReason.CompletePolyline, index, before,
  73. num6 - before, x));
  74. flag = true;
  75. }
  76. }
  77. else if (MathHelper.LessThan(x, 0.0))
  78. {
  79. if (MathHelper.GreaterThanOrClose(x + before, 0.0))
  80. {
  81. before += x;
  82. x = stopCallback(MarchLocation.Create(MarchStopReason.CompleteStep, index, before,
  83. num6 - before, 0.0));
  84. flag = true;
  85. }
  86. else if (index > 0)
  87. {
  88. index--;
  89. x += before;
  90. before = polyline.Lengths[index];
  91. // ReSharper disable once CompareOfFloatsByEqualityOperator
  92. if (flag && num5 != 1.0 && polyline.Angles[index + 1] > num5)
  93. {
  94. num6 = polyline.Lengths[index];
  95. x = stopCallback(MarchLocation.Create(MarchStopReason.CornerPoint, index, before,
  96. num6 - before, x));
  97. }
  98. }
  99. else
  100. {
  101. x += before;
  102. num6 = polyline.Lengths[index];
  103. before = 0.0;
  104. x = stopCallback(MarchLocation.Create(MarchStopReason.CompletePolyline, index, before,
  105. num6 - before, x));
  106. flag = true;
  107. }
  108. }
  109. }
  110. }
  111. }