2017-10-07 88 views
0

我正在處理圖像編輯程序。我設法弄清楚如何從圖像中選擇一個矩形,但我也喜歡手繪選擇工具。手繪選擇,複製手繪選定區域在c#

我把選擇的所有點都收集到一個列表中,這對繪圖來說足夠了,但我需要能夠確定圖像的哪些部分在選擇範圍之外以及其內部是什麼。

此外,我需要一種方法來確保選擇不會自己交叉,或者如果發生這種情況,交叉部分會合併到選擇中。

我不想找人爲我做,但我甚至不知道從哪裏開始尋找答案。

有沒有圖書館或首選的方法來做到這一點?

在此先感謝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。對於freehande的選擇考慮使用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; 
}