2011-09-15 23 views
1

4つの点構造の配列であるRectangleを持っています。任意の角度(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に)4つのポイントのいずれかを変更し、それは長方形のままように連結された点を変更します。

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

サンプル・コードは、ここに追加:私は見

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

+0

追加されたサンプルコード。それは私が分離する方法を把握することができない特定の条件を除いて動作します。 –

答えて

2

はしかし、私は私の矩形が、このような角度である場合に動作するように上記のコードを変更する必要があります2つのソリューション。最初のものは理論的には動作しますが、四捨五入のために動作しません。私はそこに最初の解決策を聞かせますが、2番目の良いものはです。

これらのサンプルでは、​​4つのコーナーCornerA、B、CおよびDを時計回りに呼びます。たとえば、「CornerA」をPoint oldPointの位置からPoint newPointに移動しているとします。

まず解決策:

  1. がサイドsideAtoB上でそのデルタの投影を行い、位置デルタ
  2. を取得し、PointDにそのベクトルを追加します。
  3. サイドsideDtoAにそのデルタの投影を行い、そのベクトルをPointBに追加します。
  4. PointAをnewPointに設定します。

第二の溶液:

  1. さんは「対角」と呼んでみましょう、移動隅の新しい位置に反対の隅を結ぶベクトルを取得します。
  2. Bの位置を "C + [sideAtoDの対角線の投影]に設定します。
  3. Dの位置を" C + [sideAtoBの対角線の投影]に設定します。
  4. PointAをnewPointに設定します。ここ

その第2の溶液のためのコードである:上記のリンクSVNリポジトリへ

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

ノーマライズ拡張機能で何をやっているのか詳しく説明できますか?この関数は "new Point()"を返します。これは常に0,0でなければなりません。何か不足していますか? –

+0

ベクトルx、yを長さで割ってベクトルを正規化する正規化()関数を意味すると仮定して、これを動作させることはできましたが、長さが0のときの扱いは分かりません。 –

+0

lol 、はい、それはベクトルを単位ベクトルに変換することになっています。私の悪い、私はちょうど私のVSの赤を削除したい: - P – Tipx

関連する問題