using o0.Geometry2D.Float; using System; namespace o0.Project { internal class o0Extension { public static void DrawLine(Matrix matrix, Line line, Func setValue, Vector size = default, bool dashedLine = false) { if (line == null || matrix == null) return; if (size == default) size = new Vector(0, 1); if (size.x != 0) { var halfExtLength = size.x / 2; var offset = new Vector(halfExtLength / line.Length * (line.B.x - line.A.x), halfExtLength / line.Length * (line.B.y - line.A.y)); line = new Line(line.A - offset, line.B + offset); } void _draw(int x, int y) { try { if (dashedLine) { var d = (new Vector(x, y) - line.A).Length; if (d % 75 < 35) matrix[x, y] = setValue(x, y); } else matrix[x, y] = setValue(x, y); } catch { } } var halfWidth = size.y / 2; if (line.A.y == line.B.y) { var xRange = ((int)Math.Round(line.A.x), (int)Math.Round(line.B.x) + 1); foreach (var y in ((int)Math.Round(line.A.y - halfWidth)).Range((int)Math.Round(line.A.y + halfWidth) + 1)) foreach (var x in xRange.Item1.Range(xRange.Item2)) _draw(x, y); return; } else if (line.A.x == line.B.x) { var yRange = ((int)Math.Round(line.A.y), (int)Math.Round(line.B.y) + 1); foreach (var x in ((int)Math.Round(line.A.x - halfWidth)).Range((int)Math.Round(line.A.x + halfWidth) + 1)) foreach (var y in yRange.Item1.Range(yRange.Item2)) _draw(x, y); return; } var upOffset = new Vector(halfWidth / line.Length * (line.A.y - line.B.y), halfWidth / line.Length * (line.B.x - line.A.x)); if (upOffset.y < 0) upOffset = -upOffset; Vector up, down, left, right; if (upOffset.x < 0)//0-90度 { up = line.B + upOffset; down = line.A - upOffset; left = line.A + upOffset; right = line.B - upOffset; } else { up = line.A + upOffset; down = line.B - upOffset; left = line.A - upOffset; right = line.B + upOffset; } var topLeft = new Line(left, up); var bottomLeft = new Line(left, down); var topRight = new Line(up, right); var bottomRight = new Line(down, right); var topLeftXToYRate = topLeft.XToYRate; var bottomLeftXToYRate = bottomLeft.XToYRate; var topRightXToYRate = topRight.XToYRate; var bottomRightXToYRate = bottomRight.XToYRate; foreach (var y in ((int)Math.Round(down.y)).Range((int)Math.Round(up.y) + 1)) foreach (var x in ((int)Math.Max(topLeft.YToX(y, topLeftXToYRate), bottomLeft.YToX(y, bottomLeftXToYRate))) .Range((int)Math.Min(topRight.YToX(y, topRightXToYRate), bottomRight.YToX(y, bottomRightXToYRate)) + 1)) _draw(x, y); } /// 计算点到直线的垂足,垂足坐标可能在Line的延长线上,可通过inLineSegment判断垂足是否在线段上 public static Vector PointPedal(Line l, in Vector v, out bool inLineSegment) { Vector d = l.B - l.A; float dotD = d.Dot(d); if (dotD == 0) throw new DivideByZeroException(); float dotL = (v - l.A).Dot(d); var factor = dotL / dotD; Vector proj = d * factor; inLineSegment = factor >= 0 && factor <= 1; return l.A + proj; } } }