Создание строк вокруг направляющей линии с использованием митержоина
Вопрос
Я рисую графики в WinForms PictureBox. Теперь я ищу возможность «дублировать» строку (массив точек), чтобы два результирующихся строки расположены непосредственное расстояние от оригинального. Как на этой картинке у меня красная линия и хочу получить черные:
Изображение линий http://img227.imageshack.us/img227/2341/Linesb.png
Я думал, что просто перемещение линии несколько пикселей вверх / вправо / вверх - вправо, но это приводит к странным перекрывающимся линиям.
Есть ли другой подход, который делает то, что я хочу? Любые идеи очень приветствуются. Спасибо!
Решение
Я создал функцию, которая делает точно Что вам нужно несколько месяцев назад в составе алгоритма макет графов. Я написал это в Python и Pyqt. Я просто вставил код Здесь в Кодепаде. Отказ Это должно быть очень легко переносимо в C #.
Обновлять:
Перевел его один на один из моего фрагмента Python (люблю делать этот графический материал :)). Поскольку мой оригинальный код был разработан для более чем двух выходных линий, я только что взял это в версию C #. Для двух черных линий - 20 пикселей от красного, просто пройти width = 40
а также num = 2
. Отказ Возвращенный язвительный массив представляет собой массив строк (внешний массив), с каждой строкой, представленной массивом точек (внутренней).
public PointF[][] MultiplyLine(PointF[] line, int width, int num)
{
if (num == 1) return new PointF[][] { line };
if (num < 1) throw new ArgumentOutOfRangeException();
if (line.Length < 2) return Enumerable.Range(0, num)
.Select(x => line).ToArray();
Func<float, float, PointF> normVec = (x, y) => {
float len = (float)Math.Sqrt((double)(x * x + y * y));
return len == 0 ? new PointF(1f, 0f) : new PointF(x / len, y / len);
};
PointF[][] newLines = Enumerable.Range(0, num)
.Select(x => new PointF[line.Length]).ToArray();
float numinv = 1f / (float)(num - 1), cor = 0f;
PointF vec1 = PointF.Empty, vec2 = PointF.Empty, vec3 = PointF.Empty;
int j = -1, i = -1;
foreach (PointF p in line)
{
bool first = j == -1, last = j == line.Length - 2; j++;
if (!last)
vec1 = normVec(line[j + 1].Y - p.Y, -line[j + 1].X + p.X);
if (!first)
vec2 = normVec(-line[j - 1].Y + p.Y, line[j - 1].X - p.X);
if (!first && !last)
{
vec3 = normVec(vec1.X + vec2.X, vec1.Y + vec2.Y);
cor = (float)Math.Sin((Math.PI -
Math.Acos(vec1.X * vec2.X + vec1.Y * vec2.Y)) / 2);
cor = cor == 0 ? 1 : cor;
vec3 = new PointF(vec3.X / cor, vec3.Y / cor);
}
i = -1;
foreach (PointF[] newLine in newLines)
{
i++; cor = (float)width * ((float)i * numinv - 0.5f);
vec1 = first ? vec1 : last ? vec2 : vec3;
newLine[j] = new PointF(vec1.X * cor + p.X, vec1.Y * cor + p.Y);
}
}
return newLines;
}
Чтобы попробовать это, я взял этот маленький образец (тот же образец, что и в моем коде PYQT):
PointF[] pts = new PointF[] {
new PointF(100f, 100f), new PointF(300f, 200f),
new PointF(500f, 200f), new PointF(300f, 500f),
new PointF(600f, 450f), new PointF(650f, 180f),
new PointF(800f, 180f), new PointF(800f, 500f),
new PointF(200f, 700f)
};
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using(Graphics g = Graphics.FromImage(pictureBox1.Image)){
g.DrawLines(new Pen(Color.Red), pts);
foreach (PointF[] line in MultiplyLine(pts, 80, 14))
g.DrawLines(new Pen(Color.Black), line);
}
Что привело к этой графике:
Контуры вокруг линии http://img41.imageshack.us/img41/8606/lines2.th.png