o0Extension.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using o0.Geometry2D.Float;
  2. using System;
  3. namespace o0.Project
  4. {
  5. internal class o0Extension
  6. {
  7. public static void DrawLine(Matrix matrix, Line line, Func<int, int, float> setValue, Geometry2D.Float.Vector size = default, bool dashedLine = false)
  8. {
  9. if (size == default)
  10. size = new Geometry2D.Float.Vector(0, 1);
  11. if (size.x != 0)
  12. {
  13. var halfExtLength = size.x / 2;
  14. var offset = new Geometry2D.Float.Vector(halfExtLength / line.Length * (line.B.x - line.A.x), halfExtLength / line.Length * (line.B.y - line.A.y));
  15. line = new Geometry2D.Float.Line(line.A - offset, line.B + offset);
  16. }
  17. int drawCount = 0;
  18. void _draw(int x, int y)
  19. {
  20. try
  21. {
  22. if (dashedLine)
  23. {
  24. if (drawCount++ % 80 < 50)
  25. matrix[x, y] = setValue(x, y);
  26. }
  27. else
  28. matrix[x, y] = setValue(x, y);
  29. }
  30. catch { }
  31. }
  32. var halfWidth = size.y / 2;
  33. if (line.A.y == line.B.y)
  34. {
  35. var xRange = ((int)Math.Round(line.A.x), (int)Math.Round(line.B.x) + 1);
  36. foreach (var y in ((int)Math.Round(line.A.y - halfWidth)).Range((int)Math.Round(line.A.y + halfWidth) + 1))
  37. foreach (var x in xRange.Item1.Range(xRange.Item2))
  38. _draw(x, y);
  39. return;
  40. }
  41. else if (line.A.x == line.B.x)
  42. {
  43. var yRange = ((int)Math.Round(line.A.y), (int)Math.Round(line.B.y) + 1);
  44. foreach (var x in ((int)Math.Round(line.A.x - halfWidth)).Range((int)Math.Round(line.A.x + halfWidth) + 1))
  45. foreach (var y in yRange.Item1.Range(yRange.Item2))
  46. _draw(x, y);
  47. return;
  48. }
  49. var upOffset = new Geometry2D.Float.Vector(halfWidth / line.Length * (line.A.y - line.B.y), halfWidth / line.Length * (line.B.x - line.A.x));
  50. if (upOffset.y < 0)
  51. upOffset = -upOffset;
  52. Geometry2D.Float.Vector up, down, left, right;
  53. if (upOffset.x < 0)//0-90度
  54. {
  55. up = line.B + upOffset;
  56. down = line.A - upOffset;
  57. left = line.A + upOffset;
  58. right = line.B - upOffset;
  59. }
  60. else
  61. {
  62. up = line.A + upOffset;
  63. down = line.B - upOffset;
  64. left = line.A - upOffset;
  65. right = line.B + upOffset;
  66. }
  67. var topLeft = new Geometry2D.Float.Line(left, up);
  68. var bottomLeft = new Geometry2D.Float.Line(left, down);
  69. var topRight = new Geometry2D.Float.Line(up, right);
  70. var bottomRight = new Geometry2D.Float.Line(down, right);
  71. var topLeftXToYRate = topLeft.XToYRate;
  72. var bottomLeftXToYRate = bottomLeft.XToYRate;
  73. var topRightXToYRate = topRight.XToYRate;
  74. var bottomRightXToYRate = bottomRight.XToYRate;
  75. foreach (var y in ((int)Math.Round(down.y)).Range((int)Math.Round(up.y) + 1))
  76. foreach (var x in ((int)Math.Max(topLeft.YToX(y, topLeftXToYRate), bottomLeft.YToX(y, bottomLeftXToYRate)))
  77. .Range((int)Math.Min(topRight.YToX(y, topRightXToYRate), bottomRight.YToX(y, bottomRightXToYRate)) + 1))
  78. _draw(x, y);
  79. }
  80. /// <summary>计算点到直线的垂足,垂足坐标可能在Line的延长线上,可通过inLineSegment判断垂足是否在线段上</summary>
  81. public static Vector PointPedal(Line l, in Vector v, out bool inLineSegment)
  82. {
  83. Vector d = l.B - l.A;
  84. float dotD = d.Dot(d);
  85. if (dotD == 0)
  86. throw new DivideByZeroException();
  87. float dotL = (v - l.A).Dot(d);
  88. var factor = dotL / dotD;
  89. Vector proj = d * factor;
  90. inLineSegment = factor >= 0 && factor <= 1;
  91. return l.A + proj;
  92. }
  93. }
  94. }