2017-10-07 2 views
0

나는 이미지 편집 프로그램을 만들고 있습니다. 이미지에서 직사각형을 선택하는 방법을 알아 냈지만 프리 핸드 선택 도구도 필요했습니다.프리 핸드 선택, 프리 핸드 선택된 영역 복사하기 #

선택 항목의 모든 포인트를 목록에 모으기 만하면 그리기에는 충분하지만 이미지의 어느 부분이 선택 항목 밖에 있고 그 안에 들어 있는지 확인할 수 있어야합니다.

또한 선택 자체가 교차하지 않는지 확인하거나 교차 부분이 선택 항목에 병합되도록하는 방법이 필요합니다.

나는 나를 위해 그것을 할 사람을 찾고있는 것이 아니지만 나는 답을 찾기 시작할 곳을 모른다.

라이브러리 또는 기본 설정 방법이 있습니까? 사전에

감사 enter image description here

내 코드 :

MouseMove 이벤트 :

  if (mdown) 
      { 
       cut_points.Add(e.Location); 

       foreach(Point p in cut_points) 
       { 
        if (p.X < cut.X || cut.X == -1) { cut.X = p.X; } 
        if (p.Y < cut.Y || cut.Y == -1) { cut.Y = p.Y; } 
        if (p.X > cut.X + cut.Width) { cut.Width = p.X - cut.X; } 
        if (p.Y > cut.Y + cut.Height) { cut.Height = p.Y - cut.Y; } 
       } 

       this.Invalidate(); 
      } 

추첨 이벤트 :

  using (Brush br = new SolidBrush(Color.FromArgb(120, Color.White))) 
      { 
       e.Graphics.FillRectangle(br, new Rectangle(0, 0, Width, Height)); 
      } 

      //Freehand 
      for (int i = 0; i < cut_points.Count; i++) 
      { 
       if(i < cut_points.Count - 1) 
       { 
        e.Graphics.DrawLine(Pens.Blue, cut_points[i], cut_points[i + 1]); 
        e.Graphics.DrawLine(Pens.Blue, new Point(cut_points[i].X + 1, cut_points[i].Y), new Point(cut_points[i + 1].X + 1, cut_points[i + 1].Y)); 
        e.Graphics.DrawLine(Pens.Blue, new Point(cut_points[i].X, cut_points[i].Y + 1), new Point(cut_points[i + 1].X, cut_points[i + 1].Y + 1)); 
       } 
       else 
       { 
        e.Graphics.DrawLine(Pens.Blue, cut_points[i], cut_points[0]); 
        e.Graphics.DrawLine(Pens.Blue, new Point(cut_points[i].X + 1, cut_points[i].Y), new Point(cut_points[0].X + 1, cut_points[0].Y)); 
        e.Graphics.DrawLine(Pens.Blue, new Point(cut_points[i].X, cut_points[i].Y + 1), new Point(cut_points[0].X, cut_points[0].Y + 1)); 
       } 
      } 

      e.Graphics.DrawRectangle(Pens.Black, cut); 
+1

봐 (https://en.wikipedia.org/wiki/Point_in_polygon) 다각형 교차 알고리즘. –

+0

@ OlivierJacot-Descombes 팁 주셔서 감사합니다! 그 부분을 살펴 보겠습니다. – WolfyD

+1

__powerful GraphicsPath__와 그 다양한 메소드를 살펴 봐야합니다! 또한 선이 연속적 일 경우 별도의 DrawLine 호출을 피하십시오. 대신 DrawLines를 사용하십시오. 자유 선택을 위해서는 DrawCurve 사용을 고려하십시오. – TaW

답변

0

OlivierJacot-Descombes 및 TAW의 도움으로 내가 필요한 해결책을 찾았습니다. 먼저 Raycasting으로 시작했으나 복잡하지 않은 다각형의 경우에만 신뢰할 만합니다. 좀 더 검색 한 후에 권선 번호가 아마도 나에게 가장 좋은 해결책이라는 것을 알았습니다.

나는 그들이 개념을 정말로 설명하고 컴퓨터 그래픽과 관련된 몇 가지 훌륭한 기능뿐만 아니라 와인딩 수 계산을위한 C 코드를 제공하는 웹 사이트를 발견했다. (URL : http://geomalgorithms.com/a03-_inclusion.html)

나는 C에서 C#으로 코드를 번역했으며 꽤 잘 작동하고있다.

코드 : [다각형 알고리즘의 포인트]에 대한

Point p = The point you need to test 
Point[] V = The vertices of the polygon as an array of Points 
//Important to note: This version of the algorithm doesn't handle a closed polygon 
//if the last Point in `V` is not V[0] as well! 
int n = V.Length - 1; 

//Returns Integer value depending on the position 
//of the tested point and a line going through 2 other points. 
//Returns >0 if Point is left of line <0 if Point is right of line and 0 if Point is on line. 
public static int isLeft(Point P0, Point P1, Point P2) 
{ 
    return ((P1.X - P0.X) * (P2.Y - P0.Y) 
     - (P2.X - P0.X) * (P1.Y - P0.Y)); 
} 

//Returns the Winding Number of the Point p against the Polygon V[n + 1] 
//V[] should contain all of the vertices of the polygon, ending with V[0] 
//n should be V.Length - 1; 
//It returns 0 if the point is outside the polygon, and any other value (Positive or negative) if it is inside 
public static int wn_PnPoly(Point P, Point[] V, int n) 
{ 
    int wn = 0; 

    // loop through all edges of the polygon 
    for (int i = 0; i < n; i++) 
    { 
     if (V[i].Y <= P.Y) 
     {   
      if (V[i + 1].Y > P.Y) 
      {  
       if (isLeft(V[i], V[i + 1], P) > 0) 
       { 
        ++wn; 
       } 
      } 
     } 
     else 
     { 
      if (V[i + 1].Y <= P.Y) 
      { 
       if (isLeft(V[i], V[i + 1], P) < 0) 
       { 
        --wn; 
       } 
      } 
     } 
    } 
     return wn; 
} 
관련 문제