2017-10-07 44 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; 
}