2016-08-18 3 views
0

パスをコピーする数学について質問があります。 のは、私はこのパスを持っているとしましょう: 距離dのパスをコピーする数学

http://imgur.com/a/42l0t

私は黒の1以外にこのパスの正確なコピーをしたいです。私は2つのポイント間の角度を計算する小さなC#プログラムを書いた。角度に応じて、XまたはY値へのオフセットが追加されます。

あなたが見ることができるように

http://imgur.com/bJQDCgq

、それはかなりありません:それは一種の作品 は、これが結果です。 今、私の本当の質問は、これに使用する適切な数学は何ですか?

うまくいけば、誰かが答えを唱えてくれるはずです。 よろしく、 サシャ

コード:

void Plot(List<Point> points) 
    { 
     Graphics g = pictureBox.CreateGraphics(); 
     g.Clear(Color.White); 

     for (int i = 0; i < points.Count - 1; i++) 
     { 
      g.DrawLine(Pens.Black, points[i], points[i + 1]); 
     } 

     List<Point> points2 = new List<Point>(); 
     for (int i = 0; i < points.Count - 1; i++) 
     { 
      var angle = getAngleFromPoint(points[i], points[i + 1]); 
      Debug.WriteLine(angle); 

      if (angle < 180 && angle >= 135) 
      { 
       points2.Add(new Point(points[i].X - OFFSET, points[i].Y)); 
      } 
      if (angle < 135 && angle >= 90) 
      { 
       if (points[i].Y < points[i + 1].Y) 
       { 
        points2.Add(new Point(points[i].X - OFFSET/2, points[i].Y + OFFSET)); 
       } 
       else 
       { 
       }     
      } 
      if (angle < 90 && angle >= 45) 
      { 
       if (points[i].Y < points[i + 1].Y) 
       { 
        points2.Add(new Point(points[i].X - OFFSET, points[i].Y)); 
       } 
       else 
       { 
        points2.Add(new Point(points[i].X + OFFSET, points[i].Y)); 
       } 
      } 
      if (angle < 45 && angle >= 0) 
      { 
       if (points[i].Y < points[i + 1].Y) 
       { 
        points2.Add(new Point(points[i].X - OFFSET, points[i].Y)); 
       } 
       else 
       { 
        points2.Add(new Point(points[i].X + OFFSET, points[i].Y)); 
       } 
      } 
      if (angle < 360 && angle >= 315) 
      { 
       if (points[i].Y < points[i + 1].Y) 
       { 
        points2.Add(new Point(points[i].X + OFFSET, points[i].Y)); 
       } 
       else 
       { 
        points2.Add(new Point(points[i].X + 10, points[i].Y - OFFSET)); 
       } 
      } 
      if (angle < 315 && angle >= 270) 
      { 
       points2.Add(new Point(points[i].X, points[i].Y - OFFSET)); 
      } 
      if (angle < 270 && angle >= 225) 
      {      
       if (points[i].Y < points[i + 1].Y) 
       { 
        points2.Add(new Point(points[i].X - OFFSET/2, points[i].Y - OFFSET)); 
       } 
       else 
       { 

       } 
      } 
      if (angle < 225 && angle >= 180) 
      { 
       if (points[i].X < points[i + 1].X) 
       { 
        points2.Add(new Point(points[i].X, points[i].Y - OFFSET)); 
       } 
       else 
       { 
        if (points[i].Y < points[i + 1].Y) //  \ 
        { 
         points2.Add(new Point(points[i].X - OFFSET, points[i].Y)); 
        } 
        else 
        { 

        } 
       } 
      } 
     } 

     for (int i = 0; i < points2.Count - 1; i++) 
     { 
      g.DrawLine(Pens.Red, points2[i], points2[i + 1]); 
     } 
    } 

私は私が結果をimnproveことができますが、よりよい解決策が存在しなければならない(多分30度まで45度ステップから)の角度を減少させる場合、私は思います。

+0

2番目の出力を与えたコードを投稿できますか? – Jack

+0

私の投稿を編集しました。それはかなり、私は知っている;) –

+0

目的の出力は何ですか?すべての線は対応する線と平行でなければなりませんか? – Jack

答えて

1

私はこれに対処する一つの方法は、ラインペア(すなわち:3ポイント)に分割することであると仮定し

ペアの各ラインの(距離dで)平行線を探します。次に、これらの平行線が交わる場所を見つけて、新しい線上の点の位置を取得します。非常に粗い擬似コードで

points a, b, c 
distance d 

lineab = findLineParallelTo(line(a,b), d) 
linebc = findLineParallelTo(line(b,c), d) 

return intersect(lineab, linebc) 
+0

それはかなり良いと思いますが、私はそれを実装し、準備が整ったらコードを投稿します。 –

0

Iは@Jackから溶液を導入し、それは素晴らしい作品:

public class Line 
{ 
    public PointF P { get; private set; } 
    public PointF Q { get; private set; } 

    public float Pitch 
    { 
     get; private set; 
    } 

    public Line() 
    { 

    } 

    public Line(float px, float py, float qx, float qy) : this(new PointF(px, py), new PointF(qx, qy)) 
    { 

    } 

    public Line(PointF p, PointF q) 
    { 
     P = p; 
     Q = q; 
    } 

    #region Methods 

    /// <summary> 
    /// http://stackoverflow.com/questions/2825412/draw-a-parallel-line 
    /// </summary> 
    public Line FindParallelLine(float distance) 
    { 
     float length = (float)Math.Sqrt((P.X - Q.X) * (P.X - Q.X) + (P.Y - Q.Y) * (P.Y - Q.Y)); 

     // This is the second line 
     float px = P.X + distance * (Q.Y - P.Y)/length; 
     float qx = Q.X + distance * (Q.Y - P.Y)/length; 
     float py = P.Y + distance * (P.X - Q.X)/length; 
     float qy = Q.Y + distance * (P.X - Q.X)/length; 

     return new Line(px, py, qx, qy); 
    }   

    public override string ToString() 
    { 
     return string.Format("P({0}|{1}), Q({2}|{3}) - Pitch: {4}", P.X, P.Y, Q.X, Q.Y, Pitch); 
    } 

    #endregion 
} 

private PointF FindIntersection(Line a, Line b) 
    { 
     PointF A = a.P; 
     PointF B = a.Q; 
     PointF C = b.P; 
     PointF D = b.Q; 

     float dy1 = B.Y - A.Y; 
     float dx1 = B.X - A.X; 
     float dy2 = D.Y - C.Y; 
     float dx2 = D.X - C.X;    

     // Check whether the two line parallel. 
     if (dy1 * dx2 == dy2 * dx1) 
     { 
      return PointF.Empty; 
     } 
     else 
     { 
      float x = ((C.Y - A.Y) * dx1 * dx2 + dy1 * dx2 * A.X - dy2 * dx1 * C.X)/(dy1 * dx2 - dy2 * dx1); 
      float y = A.Y + (dy1/dx1) * (x - A.X); 
      return new PointF(x, y); 
     } 
    } 

    private PointF FindIntersection(PointF a, PointF b, PointF c, float distance) 
    { 
     Line line1 = new Line(a, b); 
     Line line2 = new Line(b, c); 

     Line parallel = line1.FindParallelLine(distance); 
     Line parallel2 = line2.FindParallelLine(distance); 

     return FindIntersection(parallel, parallel2); 
    } 

    private List<PointF> FindIntersections(PointF[] points, float distance) 
    { 
     List<PointF> intersections = new List<PointF>(); 

     for (int i = 0; i < points.Length - 2; i++) 
     { 
      PointF intersection = FindIntersection(points[i], points[i + 1], points[i + 2], distance); 
      if (!intersection.IsEmpty && !double.IsNaN(intersection.X) && !double.IsNaN(intersection.Y)) 
      { 
       intersections.Add(intersection); 
      }     
     } 

     return intersections; 
    } 

    private PointF GetFirstPoint(PointF[] points, float distance) 
    { 
     Line parallel = new Line(points[0], points[1]).FindParallelLine(distance); 
     return parallel.P; 
    } 

    private PointF GetLastPoint(PointF[] points, float distance) 
    { 
     Line parallel = new Line(points[points.Length - 2], points[points.Length - 1]).FindParallelLine(distance); 
     return parallel.Q; 
    } 

例コール:

OFFSET = float.Parse(textBox1.Text); 
     List<PointF> points = new List<PointF>(); 
     points.Add(new PointF(200, 180)); 
     points.Add(new PointF(160, 160)); 
     points.Add(new PointF(100, 160)); 
     points.Add(new PointF(60, 140)); 
     points.Add(new PointF(40, 100)); 
     points.Add(new PointF(80, 60)); 
     points.Add(new PointF(140, 100)); 
     points.Add(new PointF(180, 140)); 
     points.Add(new PointF(220, 80)); 

     List<PointF> intersections = FindIntersections(points.ToArray(), OFFSET); 
     intersections.Insert(0, GetFirstPoint(points.ToArray(), OFFSET)); 
     intersections.Add(GetLastPoint(points.ToArray(), OFFSET)); 

     Graphics g = pictureBox.CreateGraphics(); 
     g.Clear(Color.White); 

     g.DrawLines(Pens.Black, points.ToArray()); 
     // Connect the intersection points. 
     g.DrawLines(Pens.Red, intersections.ToArray()); 

例の画像:

http://imgur.com/onUstGT

もう一度@Jack!