2011-09-07 80 views
1

我用下面的代碼行段延伸至矩形的boundry的boundry,它如果矩形內的點,但如果有一個點出了矩形的boundry做工精良它失敗限制線段矩形

enter image description here

static void extend(Rectangle bounds, ref PointF start, ref PointF end) 
     { 


     if (start != end) // this to avoid small changes in orientation 
     { 

      float slope = (end.Y - start.Y)/(end.X - start.X); 

      if (Math.Round(start.Y, 2) == Math.Round(end.Y, 2) || Math.Abs(slope) <= 0.01d) // 0.01 is offset to check if the slope is very small 
      { 
       start.X = bounds.X; 
       start.Y = start.Y; 

       end.X = bounds.X + bounds.Width; 
       end.Y = end.Y; 
       return; 

      } 

      if (Math.Round(start.X, 2) == Math.Round(end.X, 2) || Math.Abs(slope) <= 0.01d) 
      { 
       start.X = start.X; 
       start.Y = bounds.Y; 

       end.X = end.X; 
       end.Y = bounds.Y + bounds.Height; 

       return; 


      } 

      // based on (y - y1)/(x - x1) == (y2 - y1)/(x2 - x1) 
      // => (y - y1) * (x2 - x1) == (y2 - y1) * (x - x1) 

      // y_for_xmin = y1  + (y2 - y1)  * (xmin - x1)/(x2 - x1) 
      float y_for_xmin = start.Y + ((end.Y - start.Y) * (bounds.X - start.X)/(end.X - start.X)); 

      // y_for_xmax = y1 + (y2 - y1) * (xmax - x1)/(x2 - x1) 
      float y_for_xmax = start.Y + ((end.Y - start.Y) * (bounds.X + bounds.Width - start.X)/(end.X - start.X)); 

      // x_for_ymin = x1 + (x2 - x1) * (ymin - y1)/(y2 - y1) 

      float x_for_ymin = start.X + ((end.X - start.X) * (bounds.Y - start.Y)/(end.Y - start.Y)); 


      //x_for_ymax = x1 + (x2 - x1) * (ymax - y1)/(y2 - y1) 
      float x_for_ymax = start.X + ((end.X - start.X) * (bounds.Y + bounds.Height - start.Y)/(end.Y - start.Y)); 



      if ((bounds.Y <= y_for_xmin) && (y_for_xmin <= bounds.Y + bounds.Height)) 
      { 



       if ((bounds.X <= x_for_ymax) && (bounds.X <= bounds.X + bounds.Width)) 
       { 
        start.X = bounds.X; 
        start.Y = y_for_xmin; 

        end.X = x_for_ymax; 
        end.Y = bounds.Y + bounds.Height; 
        return; 
       } 

       if ((bounds.X <= x_for_ymin && x_for_ymin <= bounds.X + bounds.Width)) 
       { 
        start.X = bounds.X; 
        start.Y = y_for_xmin; 

        end.X = x_for_ymin; 
        end.Y = bounds.Y; 
        return; 

       } 

      } 

      if ((bounds.Y <= y_for_xmax) && (bounds.Y <= bounds.Y + bounds.Height)) 
      { 
       if ((bounds.X <= x_for_ymin) && (x_for_ymin <= bounds.X + bounds.Width)) 
       { 
        start.X = x_for_ymin; 
        start.Y = bounds.Y; 

        end.X = bounds.X + bounds.Width; 
        end.Y = y_for_xmax; 

        return; 

       } 
       if ((bounds.X <= x_for_ymax) && (x_for_ymax <= bounds.X + bounds.Width)) 
       { 

        start.X = x_for_ymax; 
        start.Y = bounds.Y + bounds.Height; 

        end.X = bounds.X + bounds.Width; 
        end.Y = y_for_xmax; 
        return; 

       } 
      } 


     } 





    } 

任何想法如何解決線上的點的情況下出來的矩形

+0

因爲你正在檢查它是否在矩形內..... –

+0

如何檢查外部請處理 – AMH

+0

@AMH:你想保留點在矩形外的位置? – Jiri

回答

1
static bool intersection(PointF a1, PointF a2, PointF b1, PointF b2, ref PointF ans) 
{ 
    float x = ((a1.X*a2.Y - a1.Y*a2.X)*(b1.X - b2.X) - (a1.X - a2.X)*(b1.X*b2.Y - b1.Y*b2.X))/((a1.X - a2.X)*(b1.Y - b2.Y) - (a1.Y - a2.Y)*(b1.X - b2.X)); 
    float y = ((a1.X*a2.Y - a1.Y*a2.X)*(b1.Y - b2.Y) - (a1.Y - a2.Y)*(b1.X*b2.Y - b1.Y*b2.X))/((a1.X - a2.X)*(b1.Y - b2.Y) - (a1.Y - a2.Y)*(b1.X - b2.X)); 

    if(x == float.NaN || x == float.PositiveInfinity || x == float.NegativeInfinity || y == float.NaN || y == float.PositiveInfinity || y == float.NegativeInfinity) 
    { // the lines are equal or never intersect 
    return false; 
    } 
    ans.X = x; 
    ans.Y = y; 
    return true; 
} 

static void extend(Rectangle bounds, ref PointF start, ref PointF end) 
{ 

    List<PointF> ansFinal = new List<PointF>(); 
    PointF ansLeft = new PointF(); 
    bool hitLeft = intersection(start, end, new PointF(bounds.X, bounds.Y), new PointF(bounds.X, bounds.Y + bounds.Height), ansLeft); 
    if(hitLeft && (ansLeft.Y < bounds.Y || ansLeft.Y > bounds.Y + bounds.Height)) hitLeft = false; 
    if(hitLeft) ansFinal.Add(ansLeft); 

    PointF ansTop = new PointF(); 
    bool hitTop = intersection(start, end, new PointF(bounds.X, bounds.Y), new PointF(bounds.X + bounds.Width, bounds.Y), ansTop); 
    if(hitTop && (ansTop.X < bounds.X || ansTop.X > bounds.X + bounds.Width)) hitTop = false; 
    if(hitTop) ansFinal.Add(ansTop); 

    PointF ansRight = new PointF(); 
    bool hitRight = intersection(start, end, new PointF(bounds.X + bounds.Width, bounds.Y), new PointF(bounds.X + bounds.Width, bounds.Y + bounds.Height), ansRight); 
    if(hitRight && (ansRight.Y < bounds.Y || ansRight.Y > bounds.Y + bounds.Height)) hitRight = false; 
    if(hitRight) ansFinal.Add(ansRight); 

    PointF ansBottom = new PointF(); 
    bool hitBottom = intersection(start, end, new PointF(bounds.X, bounds.Y + bounds.Height), new PointF(bounds.X + bounds.Height, bounds.Y + bounds.Height), ansBottom); 
    if(hitBottom && (ansBottom.X < bounds.X || ansBottom.X > bounds.X + bounds.Width)) hitBottom = false; 
    if(hitBottom) ansFinal.Add(ansBottom); 

    if(!hitLeft && !hitTop && !hitRight && !hitBottom) 
    { 
    throw new Exception("No interections"); 
    } 
    /* 
    // IF YOU HAD LINQ 
    PointF[] ans = ansFinal.Distinct().ToArray(); 
    if(ans.Length < 2) 
    { 
    throw new Exception("Corner case *wink*"); 
    } 
    start.X = ans[0].X; start.Y = ans[0].Y; 
    end.X = ans[1].X; end.Y = ans[1].Y; 
    */ 

    // the following is sufficient to cull out corner to corner, one corner 
    for(int x=ansFinal.Count-1; x>=1; x--) 
    if(ansFinal[x] == ansFinal[x-1]) 
    ansFinal.RemoveAt(x); 
    if(ansFinal.Count < 2) 
    { 
    throw new Exception("Corner case *wink*"); 
    } 

    start.X = ansFinal[0].X; start.Y = ansFinal[0].Y; 
    end.X = ansFinal[1].X; end.Y = ansFinal[1].Y; 

} 

編輯我寫這在瀏覽器內因此可能會有一些語法錯誤......

的概念是你使用測試線到線的交點與矩形的兩側。如果存在交點,請確保它位於矩形邊(線段)的範圍內。