o0Extension.cs 4.3 KB

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