2016-08-18 1 views
0

경로 복사에 관련된 질문이 있습니다. 의 내가이 경로 있다고 가정 해 봅시다 : 거리가 d 인 경로를 복사하는 수학

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

나는 검은 하나 외에이 경로의 정확한 사본을 원한다. 두 점 사이의 각도를 계산하는 작은 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

두 번째 출력을 제공하는 코드를 게시 할 수 있습니까? – Jack

+0

내 게시물을 편집했습니다. 귀엽지는 않아요.) –

+0

의도 한 결과는 무엇입니까? 모든 라인이 그 대응 물과 평행해야합니까? – Jack

답변

1

는 난이 라인 쌍 (예 : 세 점)으로 분할하는 해결 방법 중 하나를 가정

쌍의 각 라인 (거리 (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

나는 @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

다시 한번 감사드립니다. @ 잭!

관련 문제