J'ai créé une fonction qui fait exactement ce dont vous avez besoin il y a quelques mois dans le cadre d'un algorithme de disposition de graphe. J'ai écrit ça en python et PyQt. Je viens de coller le code here at codepad. Cela devrait être très facilement traduisible en C#.
Mise à jour:
traduit un à un de mon extrait de python (Love à faire ce genre de choses graphiques :)). Comme mon code original a été conçu pour plus de deux lignes de sortie, je l'ai simplement pris dans la version C#. Pour deux lignes noires étant à 20 pixels de la ligne rouge, il suffit de passer width = 40
et num = 2
. Le tableau jagged retourné représente un tableau de lignes (tableau externe), avec chaque ligne représentée par un tableau de points (interne).
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;
}
Pour l'essayer, je pris ce petit échantillon (le même échantillon que dans mon code 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);
}
Ce qui a donné lieu à ce graphique:
outlines around line http://img41.imageshack.us/img41/8606/lines2.th.png
Notez que les lignes noires n'ont pas la même taille que la ligne rouge. – SLaks