2011-09-15 60 views
1

我有一個矩形,它是一個4點結構的數組。它可以在任何角度(0到360度)上旋轉,並且可以正確繪製。調整角度上的矩形

用戶還可以拖動角來調整矩形。例如,如果它們移動左下角的點,它也將更新左上點的X座標和右下點的Y座標。這樣,無論他們移動哪個點,它總是一個矩形。

Points[point] = newValue; 

switch (point) 
{ 
    case TopLeft: 
     Points[BottomLeft].X = newValue.X; 
     Points[TopRight].Y = newValue.Y; 
     break; 

    case BottomRight: 
     Points[TopRight].X = newValue.X; 
     Points[BottomLeft].Y = newValue.Y; 
     break; 

    case BottomLeft: 
     Points[TopLeft].X = newValue.X; 
     Points[BottomRight].Y = newValue.Y; 
     break; 

    case TopRight: 
     Points[BottomRight].X = newValue.X; 
     Points[TopLeft].Y = newValue.Y; 
     break; 
} 

在這裏,我改變任何的四個點的給定的輸入點(newValue)以,然後修改鏈接點,使得它保持一個矩形形狀。

不過,我需要修改上面的代碼工作,如果我的矩形是在這樣的一個角度:添加這裏

http://thesaurus.maths.org/mmkb/media/png/Rectangle.png

示例代碼:

http://www.assembla.com/code/moozhe-testing/subversion/nodes/rotateRectangle

+0

添加示例代碼上面鏈接的SVN庫。它在除了某些我無法弄清楚如何隔離的條件下工作。 –

回答

2

我見2解決方案。第一個理論上可行,但由於四捨五入,它最終不起作用。我會讓第一個解決方案在那裏,但第二個是好的一個

在這些樣品中,我將調用4個角CornerA,B,C和d,以順時針方式命名。假設您正在將「CornerA」從位置Point oldPoint移動到位置Point newPoint

解決方案一:

  1. 獲取位置增量
  2. 請在側sideAtoB是增量的投影和矢量添加到PointD。
  3. 在一側對該增量進行投影,並將該矢量添加到Point B.
  4. 將PointA設置爲newPoint。

解決方法二:

  1. 獲取矢量對面的角落鏈接到活動角的新位置,讓我們把它稱爲「對角線」。
  2. 集B的位置移動到「C + [上sideAtoD的傾斜投射。
  3. 集D的位置,以」 C + [上sideAtoB的傾斜投射。
  4. 將PointA設置爲newPoint。

下面是該第二溶液的代碼:

public class Rectangle 
{ 
    // Obviously, one would need to assign values to these points. 
    Point CornerA = new Point(); 
    Point CornerB = new Point(); 
    Point CornerC = new Point(); 
    Point CornerD = new Point(); 
    Dictionary<int, Point> points = new Dictionary<int, Point>(); 

    public Rectangle() 
    { 
     points.Add(0, CornerA); 
     points.Add(1, CornerB); 
     points.Add(2, CornerC); 
     points.Add(3, CornerD); 
    } 

    public void MoveAPoint(int id, Point newPoint) 
    { 
     // Get the old point 
     Point oldPoint = points[id]; 
     // Get the previous point 
     Point pointPrevious = points[(id + 3) % 4]; 
     // Get the next point 
     Point pointNext = points[(id + 1) % 4]; 
     // Get the opposite point 
     Point pointOpposite = points[(id + 2) % 4]; 
     // Get the delta (variation) of the moving point 
     Point delta = newPoint.Substract(oldPoint); 

     // I call sides points, but they are actually vectors. 
     // Get side from 'oldPoint' to 'pointPrevious'. 
     Point sidePrevious = pointPrevious.Substract(oldPoint); 

     // Get side from 'oldPoint' to 'pointNext'. 
     Point sideNext = pointNext.Substract(oldPoint); 

     // Get side from 'pointOpposite' to 'newPoint'. 
     Point sideTransversal = newPoint.Substract(pointOpposite); 

     PointF previousProjection; 
     PointF nextProjection; 

     if (sideNext.X == 0 && sideNext.Y == 0) 
     { 
      if (sidePrevious.X == 0 && sidePrevious.Y == 0) 
      { 
       return; 
      } 

      sideNext = new PointF(-sidePrevious.Y, sidePrevious.X); 
     } 
     else 
     { 
      sidePrevious = new PointF(-sideNext.Y, sideNext.X); 
     } 

     Point previousProjection = Projection(delta, sidePrevious); 
     Point nextProjection = Projection(delta, sideNext); 

     pointNext.SetToPoint(pointNext.AddPoints(previousProjection)); 
     pointPrevious.SetToPoint(pointPrevious.AddPoints(nextProjection)); 
     oldPoint.SetToPoint(newPoint); 
    } 

    private static Point Projection(Point vectorA, Point vectorB) 
    { 
     Point vectorBUnit = new Point(vectorB.X, vectorB.Y); 
     vectorBUnit = vectorBUnit.Normalize(); 

     decimal dotProduct = vectorA.X * vectorBUnit.X + vectorA.Y * vectorBUnit.Y; 
     return vectorBUnit.MultiplyByDecimal(dotProduct); 
    } 
} 

public static class ExtendPoint 
{ 
    public static Point Normalize(this Point pointA) 
    { 
     double length = Math.Sqrt(pointA.X * pointA.X + pointA.Y * pointA.Y); 
     return new Point(pointA.X/length, pointA.Y/length); 
    } 

    public static Point MultiplyByDecimal (this Point point, decimal length) 
    { 
     return new Point((int)(point.X * length), (int)(point.Y * length)); 
    } 

    public static Point AddPoints(this Point firstPoint, Point secondPoint) 
    { 
     return new Point(firstPoint.X + secondPoint.X, firstPoint.Y + secondPoint.Y); 
    } 

    public static Point Substract(this Point firstPoint, Point secondPoint) 
    { 
     return new Point(firstPoint.X - secondPoint.X, firstPoint.Y - secondPoint.Y); 
    } 

    public static void SetToPoint(this Point oldPoint, Point newPoint) 
    { 
     oldPoint.X = newPoint.X; 
     oldPoint.Y = newPoint.Y; 
    } 
} 
+0

你能詳細說明Normalize擴展應該做什麼嗎?該函數返回「新的Point()」,它應該始終爲0,0。我錯過了什麼嗎? –

+0

假設你的意思是Normalize()函數通過將向量x,y除以長度來規範化向量,我已經能夠得到這個工作,但是當長度爲0時我不知道如何處理。 –

+0

大聲笑,是的,它應該將矢量轉換爲單位矢量。我的壞,我只是想刪除我的VS中的紅色:-P – Tipx