2011-09-15 59 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