2010-04-20 5 views
3

Je dessine des graphiques dans une WinForms Picturebox. Maintenant, je cherche une possibilité de 'dupliquer' une ligne (un tableau de points), de sorte que les deux lignes résultantes soient positionnées à une distance fixe de la ligne d'origine. Comme dans cette image, j'ai la ligne rouge et que vous souhaitez obtenir les noirs:Créer des lignes autour d'une ligne de guidage en utilisant Mitrejoin

Picture of lines http://img227.imageshack.us/img227/2341/linesb.png

Je pensais à juste déplacer la ligne quelques pixels vers le haut/droite/haut droit, mais qui mène à étrange lignes qui se chevauchent.

Y at-il une autre approche qui fait ce que je veux? Toutes les idées seraient grandement appréciées. Merci!

+0

Notez que les lignes noires n'ont pas la même taille que la ligne rouge. – SLaks

Répondre

2

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

+0

Cela semble être très prometteur. J'ai peur que je n'ai pas la moindre idée de python. –

+0

Wow, c'est génial! Merci beaucoup, c'est parfaitement ce que je cherchais, et une réponse vraiment rapide et détaillée! –

Questions connexes