簡體   English   中英

如何在旋轉的畫布上准確繪制橡皮筋選擇矩形?

[英]How to Draw a Rubber Band Selection Rectangle accurately on a Rotated Canvas?

這是在畫布上繪制的橡皮筋選擇矩形。 我的問題是,只要不旋轉畫布內容,就很容易獲得矩形的正確大小。 但是,矩形一旦旋轉,便不再具有光標的大小。 我需要橡皮筋與屏幕保持平行

   var dragPt = new PointF(e.Position.X - G.ReferenceOffset.X, e.Position.Y - G.ReferenceOffset.Y);

    var rotation = ADEEnvironment.RotateAngle;

    var width = (dragPt.X - pressPt.X);
    var height = (dragPt.Y - pressPt.Y);

該代碼非常簡單。 我按下鼠標時捕獲了鼠標的位置:pressPt。 在鼠標移動事件中,我獲得了當前的鼠標位置dragPt,並計算了橡皮筋矩形的寬度和高度,並使用這些值創建了一個矩形,其原點位於pressPt上。

如果畫布的相機未旋轉,則效果很好。 旋轉顯示器時,我需要橡皮筋與屏幕保持對齊,而不是與繪制在畫布上的對齊。 我只是離開它,橡皮筋也被拉動旋轉。

如果我旋轉橡皮筋矩形以使其與屏幕對齊,則矩形將無法正確調整大小。 因此,經過一番混亂之后,我嘗試了一些三角函數:

    var width = (float)((dragPt.X - pressPt.X) / Math.Cos(rotation));
    var height = (float)((dragPt.Y - pressPt.Y) / Math.Cos(rotation));

鑒於旋轉角度可以是0> 360的任何角度,這不起作用並且變得非常混亂

我看過其他有關如何創建選擇矩形的代碼,包括以下問題的答案: 如何制作可調整大小的矩形選擇工具? 但我想盡可能使用我擁有的基本代碼,因為它與我使用的圖形引擎(Piccolo)有關。

我會放一些屏幕截圖,但是我無法捕捉橡皮筋。 我認為這比其他任何問題更多的是數學問題,並且應該易於修復,但是我無法計算出要考慮旋轉顯示效果的數學計算。

此代碼使用Paint事件繪制

  • 旋轉畫布上的一個固定矩形
  • 未旋轉的副本
  • 不旋轉的橡皮筋

  • 並檢查示例矩形的角落


// one example 'object'
Rectangle R0 = new Rectangle(182,82,31,31);

// a few helpers
Point curMouse = Point.Empty;
Point downMouse = Point.Empty;
Rectangle RM = Rectangle.Empty;

float angle = 30;
Point center = new Point(-55, -22);

private void canvas_Paint(object sender, PaintEventArgs e)
{
    // preprare the canvas to rotate around a center point:
    e.Graphics.TranslateTransform(center.X , center.Y);
    e.Graphics.RotateTransform(angle);
    e.Graphics.TranslateTransform(-center.X, -center.Y);
    // draw one object and reset
    e.Graphics.DrawRectangle(Pens.Green, R0);
    e.Graphics.ResetTransform();

    // for testing (and hittesting): this is the unrotated obejct:
    e.Graphics.DrawRectangle(Pens.LightGray, R0);

    // allowing for any way the rubber band is drawn..
    // ..should be moved to a helper function!  
    Size S = new Size( Math.Abs(downMouse.X - curMouse.X), 
                       Math.Abs(downMouse.Y - curMouse.Y));
    Point P0 = new Point(Math.Min(downMouse.X, curMouse.X), 
                       Math.Min(downMouse.Y, curMouse.Y));
    RM = new Rectangle(P0, S);
    // the ruber band
    e.Graphics.DrawRectangle(Pens.Red, RM);

}

private void canvas_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    curMouse = e.Location;
    canvas.Invalidate();
}

private void canvas_MouseDown(object sender, MouseEventArgs e)
{
    downMouse = e.Location;
    curMouse = e.Location;
}

IMO,更有趣的部分將是決定選擇哪些對象。 會不會有任何路口計數或應該將其完全包含?

在這篇文章中找到了一段不錯的旋轉代碼並添加了一個示例來檢查固定的Rectangle

當然,更復雜的對象將需要更多的點列表。 為了獲得真正准確的結果,您甚至可能需要使用GraphicsPaths及其支持的Regions上的set操作。 但是也許一個簡單的凸包就可以了。

當然,您將要存儲旋轉的點,而不是重復地計算它們。

static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
{
    double angleInRadians = angleInDegrees * (Math.PI / 180);
    double cosTheta = Math.Cos(angleInRadians);
    double sinTheta = Math.Sin(angleInRadians);
    return new Point
    {
        X =
            (int)
            (cosTheta * (pointToRotate.X - centerPoint.X) -
            sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
        Y =
            (int)
            (sinTheta * (pointToRotate.X - centerPoint.X) +
            cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
    };
}

private void canvas_MouseUp(object sender, MouseEventArgs e)
{

    List<Point> points = new List<Point>();
    points.Add(RotatePoint(new Point(R0.Left, R0.Top), center, angle));
    points.Add(RotatePoint(new Point(R0.Right, R0.Top), center, angle) );
    points.Add(RotatePoint(new Point(R0.Right, R0.Bottom), center, angle) );
    points.Add(RotatePoint(new Point(R0.Left, R0.Bottom), center, angle));

    bool ok = true;
    foreach (Point pt in points) if (!RM.Contains(pt)) ok = false;

    if (ok) this.Text = "HIT"; else this.Text = "no hit";
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM