将矩形旋转任意角度后,如何计算矩形的正确边界(Canvas.SetTop和Canvas.SetLeft)

时间:2018-10-26 10:10:32

标签: c# wpf canvas

我具有以下ui元素:enter image description here

它们是5个独立的矩形,一条直线和一个椭圆(wpf元素)。设置此选项后,我将计算大矩形的角点并保存它们。 我用Canvas.SetLeft和Canvas.SetTop定位整个内容。 现在,用户可以旋转此构造。 这是我的问题:旋转后如何为所有元素计算SetTop和SetLeft的正确值?我需要它们来计算旋转后发生的平移和调整大小的位置。

EDIT1

private Canvas
    contentContainer;

private bool
    isMoving = false,
    isRotating = false,
    isLoading = true,
    isResizing = false,
    needRotationCenterUpdate = true,
    isInBounds = false,
    isRedrawing = false;

/// <summary>
/// position of mouse cursor at buttondown event relative to map
/// </summary>
private Point
    initialMoveScreenPosition;
/// <summary>
/// position of mouse cursor at buttondown event relative to surroundingRectangle
/// </summary>
private Point
    initialMoveScreenOffset;
/// <summary>
/// map coordinates of initialMoveScreenPosition
/// </summary>
private LonLat
    initialMoveMapPosition = null;

public Point
    ConnectionLineDirection
{ get; set; }

private Point
    rotationCenter,
    cornerA,
    cornerB,
    cornerC,
    cornerD,
    activeCorner;

private MouseButtonEventHandler
    selectHandler,
    mouseDownHandler,
    mouseUpHandler;

private MouseEventHandler
    mouseMoveHandler;

private FrameworkElement
    surroundingRectangle = null;

private LonLat
    centerPosition,
    northPosition;

private Ellipse
    rotationSign;

private Line
    connectionLine;

private Rectangle
    resizeCorner1,
    resizeCorner2,
    resizeCorner3,
    resizeCorner4,
    activeResizeCorner;

private double
    oldAngle,
    angle,
    distance,
    rotationSignLeft = double.NaN,
    rotationSignTop= double.NaN,
    OrigOffsetLeft= double.NaN,
    OrigOffsetTop= double.NaN;

public RotateTransform
    rotateSurroundingRectangle,
    rotateResizeCorner1,
    rotateResizeCorner2,
    rotateResizeCorner3,
    rotateResizeCorner4,
    rotateRotationSign;

this.mouseDownHandler = new MouseButtonEventHandler((s, a) =>
{
    this.OrigOffsetLeft = Canvas.GetLeft(this.contentContainer);
    this.OrigOffsetTop = Canvas.GetTop(this.contentContainer);
    if (s.Equals(this.surroundingRectangle))
    {
        // Check, if the mouse interaction is a valid start of movement
        if (this.ParentLayer != null && a.LeftButton == MouseButtonState.Pressed)// && !this.isMoving)
        {
            // Select this control
            this.IsSelected = true;

            // Element is now moved
            this.isMoving = true;
            this.isRotating = false;
            this.isResizing = false;
            // Get the initial move positions
            this.initialMoveScreenPosition = a.GetPosition(this.ParentLayer);
            this.initialMoveScreenOffset = a.GetPosition(this.surroundingRectangle);
            this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);

            // Capture the mouse while dragging
            this.surroundingRectangle.CaptureMouse();

            // Mouse movement was handled
            a.Handled = true;

            // Remove the cursor
            this.surroundingRectangle.Cursor = this.SetCursorDependingOnPosition();
        }
    }
    else if (s.Equals(this.rotationSign))
    {
        if (this.ParentLayer != null && a.LeftButton == MouseButtonState.Pressed )
        {
            // Select this control
            this.IsSelected = true;

            this.isMoving = false;
            this.isRotating = true;
            this.isResizing = false;

            // Get the initial move positions
            this.initialMoveScreenPosition = a.GetPosition(this.ParentLayer);
            this.initialMoveScreenOffset = a.GetPosition(this.surroundingRectangle);
            this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);


            // Mouse movement was handled
            this.rotationSign.CaptureMouse();
            a.Handled = true;
        }
    }
    else if (s.Equals(this.resizeCorner1) || s.Equals(this.resizeCorner2) || s.Equals(this.resizeCorner3) || s.Equals(this.resizeCorner4))
    {
        this.IsSelected = true;
        this.isMoving = false;
        this.isRotating = false;
        this.isResizing = true;
        this.initialMoveScreenPosition = a.GetPosition(this.ParentLayer);
        this.initialMoveScreenOffset = a.GetPosition(this.surroundingRectangle);
        this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);
        SetResizeCornerPosition();
        this.SetActiveCorner();
        a.Handled = true;
    }
}


.mouseMoveHandler = new MouseEventHandler((s, a) =>
{
    // Check, if the left button is pressed
    if (this.ParentLayer != null && a.LeftButton == MouseButtonState.Pressed)
    {
        if (this.isMoving)
        {
            this.Move(a);
        }
        else if (this.isResizing)
        {
            this.Resize(a);
        }
        else if (this.isRotating)
        {
            this.Rotate(a);
        }

    }
    else
    {
        // Mouse is no longer moved
        this.isMoving = false;

        // Stop capturing the mouse
        this.surroundingRectangle.ReleaseMouseCapture();

        // Remove the cursor

        this.surroundingRectangle.Cursor = this.SetCursorDependingOnPosition();
    }
}

.mouseUpHandler = new MouseButtonEventHandler((s, a) =>
{
    if (a.LeftButton != MouseButtonState.Pressed)
    {
        // Check, if the left button is released
        if (this.isMoving)
        {
            // Mouse is no longer moved
            this.isMoving = false;
            this.isResizing = false;
            this.isRotating = false;
            this.activeCorner = this.rotationCenter;
            // Stop capturing the mouse
            this.surroundingRectangle.ReleaseMouseCapture();

            // Remove the cursor
            this.surroundingRectangle.Cursor = this.SetCursorDependingOnPosition();
        }
    }

}


private void Rotate(MouseEventArgs e)

   if (e.LeftButton == MouseButtonState.Pressed)
   {
       // Get the current screen and map position
       Point currentScreenPosition = e.GetPosition(this.ParentLayer);


       // Calculate orientation and distance
       this.northPosition = this.ParentLayer.GetPosition(currentScreenPosition);
       this.oldAngle = angle;
       this.angle = this.centerPosition.AngleTo(this.northPosition);
       this.distance = this.centerPosition.DistanceTo(this.northPosition);

       // Handle the change of the bounds
       this.HandleBoundsChanged();

       // Allow the extending methods to handle the change of the location
       this.HandleLocationChanged();

       // Raise event
       if (this.LoacationChanged != null) this.LoacationChanged(this, null);

       // Avoid other mouse events
       e.Handled = true;
   }
   else
   {
       // Select this control
       this.IsSelected = true;

       // Element is now moved

       // Get the initial move positions
       this.initialMoveScreenPosition = e.GetPosition(this.ParentLayer);
       this.initialMoveScreenOffset = e.GetPosition(this.rotationSign);
       this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);

       e.Handled = true;
   }
}

private void Move(MouseEventArgs a)
    {
        // Get change in x and y direction
        double moveX = a.GetPosition(this.ParentLayer).X - this.initialMoveScreenPosition.X;
        double moveY = a.GetPosition(this.ParentLayer).Y - this.initialMoveScreenPosition.Y;

        //set the new positions
        this.rotationCenter.X += moveX;
        this.rotationCenter.Y += moveY;
        this.needRotationCenterUpdate = true;

        this.OrigOffsetLeft += moveX;
        this.OrigOffsetTop += moveY;

        this.rotationSignLeft += moveX;
        this.rotationSignTop += moveY;

        this.cornerA.X += moveX;
        this.cornerA.Y += moveY;
        this.cornerB.X += moveX;
        this.cornerB.Y += moveY;
        this.cornerC.X += moveX;
        this.cornerC.Y += moveY;
        this.cornerD.X += moveX;
        this.cornerD.Y += moveY;

        this.ConnectionLineDirection = new Point(this.ConnectionLineDirection.X + moveX, this.ConnectionLineDirection.Y + moveY);
        this.needRotationCenterUpdate = true;
        this.HandleCenterPositionChanged(this.rotationCenter);

        // Refresh the position of this control and raise event
        this.HandleBoundsChanged();
        if (this.LoacationChanged != null) this.LoacationChanged(this, null);
        this.initialMoveScreenPosition = a.GetPosition(this.ParentLayer);
        this.initialMoveScreenOffset = a.GetPosition(this.rotationSign);
        this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);
        // Avoid other mouse events
        a.Handled = true;

        // Remove the cursor
        this.surroundingRectangle.Cursor = this.SetCursorDependingOnPosition();
    }

private void Resize(MouseEventArgs a)
{
    if(a.LeftButton == MouseButtonState.Pressed)
    {

        Point mousepos = a.GetPosition(this.ParentLayer);
        double moveX = Math.Abs(this.initialMoveScreenPosition.X - mousepos.X);
        double moveY = Math.Abs(this.initialMoveScreenPosition.Y - mousepos.Y);
        double move = moveX > moveY ? moveX : moveY;

        double width;
        double height;

        //if (this.angle != 0)
        //{
        //    ReturnToStandartCase();
        //}

        double dis1 = this.rotationCenter.CalculateDistance(mousepos) + this.initialMoveScreenPosition.CalculateDistance(this.activeCorner);
        double dis2 = this.rotationCenter.CalculateDistance(this.activeCorner);
        if (dis1 < dis2)
        {
            width = this.contentContainer.Width - move;
            height = this.contentContainer.Height - move;
            if (width > 3 * resizeCornerSize)
            {
                this.contentContainer.Width = width;
                this.contentContainer.Height = height;
                this.OrigOffsetLeft += move/2;
                this.OrigOffsetTop += move/2;
                this.rotationSignTop += move/2;
            }
        }
        else
        {
            width = this.contentContainer.Width + move;
            height = this.contentContainer.Height + move;
            if (width > 3 * resizeCornerSize)
            {
                this.contentContainer.Width = width;
                this.contentContainer.Height = height;
                this.OrigOffsetLeft -= move/2;
                this.OrigOffsetTop -= move/2;
                this.rotationSignTop -= move / 2;
            }
        }
        //Logger.Logger.Write("C:\\Users\\Maik\\Desktop\\coord.log", "Top,Left,Bottom,Right: " + Canvas.GetTop(this.contentContainer) + " ; " + Canvas.GetLeft(this.contentContainer) + " ; " + Canvas.GetBottom(this.contentContainer) + " ; " + Canvas.GetRight(this.contentContainer));



        this.HandleResize(this.contentContainer.Width, this.contentContainer.Height);
        this.HandleBoundsChanged();
        // Allow the extending methods to handle the change of the location
        this.HandleLocationChanged();
        this.initialMoveScreenPosition = a.GetPosition(this.ParentLayer);
        this.initialMoveScreenOffset = a.GetPosition(this.rotationSign);
        this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);

        // Raise event
        if (this.LoacationChanged != null) this.LoacationChanged(this, null);
        a.Handled = true;
    }
    else
    {
        // Select this control
        this.IsSelected = true;

        // Element is now moved

        // Get the initial move positions
        this.initialMoveScreenPosition = a.GetPosition(this.ParentLayer);
        this.initialMoveScreenOffset = a.GetPosition(this.rotationSign);
        this.initialMoveMapPosition = this.ParentLayer.GetPosition(this.initialMoveScreenPosition);

        a.Handled = true;
    }

}

public override void HandleBoundsChanged()
{
    // Check, if the center position is defined
    if (this.centerPosition != null && this.ParentLayer != null )
    {
        // Get the position of this element on the parent screen

        Point centerPositionOnScreen = this.ParentLayer.GetPosition(this.centerPosition);
        this.HandleCenterPositionChanged(centerPositionOnScreen);

        // Make the content container become visible
        if (this.contentContainer.Visibility != Visibility.Visible) this.contentContainer.Visibility = Visibility.Visible;
        // Calculate the bounds of this element on the screen
        double halfwidth;
        double halfheight;

        if (double.IsNaN(this.OrigOffsetLeft))
        {
            halfwidth = this.contentContainer.Width / 2;
            halfheight = this.contentContainer.Height / 2;
            this.OrigOffsetLeft = centerPositionOnScreen.X - halfwidth;
            //this.OrigOffsetTop = centerPositionOnScreen.X + halfwidth;
            this.OrigOffsetTop = centerPositionOnScreen.Y - halfheight;
            //y1 = centerPositionOnScreen.Y + halfheight;
        }


        // Locate the content container on the screen
        Canvas.SetLeft(this.contentContainer, this.OrigOffsetLeft);
        Canvas.SetTop(this.contentContainer, this.OrigOffsetTop);
        Canvas.SetRight(this.contentContainer, this.ParentLayer.Width - (this.OrigOffsetLeft + this.contentContainer.Width));
        Canvas.SetBottom(this.contentContainer, this.ParentLayer.Width - (this.OrigOffsetTop + this.contentContainer.Height));

        // Check, if the move overlay needs to be set
        if (this.IsSelected)
        {
            // Make sure, the selection is visible
            this.EnsureSeclectionAdded();

            // Locate the surrounding rectangle
            Canvas.SetLeft(this.surroundingRectangle, this.OrigOffsetLeft);
            Canvas.SetTop(this.surroundingRectangle, this.OrigOffsetTop);
            //Canvas.SetRight(this.surroundingRectangle, this.ParentLayer.Width - x1);
            //Canvas.SetBottom(this.surroundingRectangle, this.ParentLayer.Width - y1);
            this.surroundingRectangle.Width = this.contentContainer.Width;
            this.surroundingRectangle.Height = this.contentContainer.Height;

            if (this.ConnectionLineDirection.X == -1 || this.ConnectionLineDirection.Y == -1)
            {
                this.SetCornerPoints();
            }

            if (this.isLoading)
            {
                this.SetResizeCorners();
                this.rotationCenter = this.cornerA.CalculatePointOnLine(this.cornerC, 0.5);
                this.SetConnectionLine();
                this.SetRotationSign();

                //this.rotationTest();

                this.isLoading = false;
            }
            if (isRotating)
            {
                // Refresh the rotation transform
                if (this.needRotationCenterUpdate)
                {
                    this.RefreshRotationCenter();
                    this.needRotationCenterUpdate = false;
                }

                this.rotateSurroundingRectangle.Angle = this.angle;
                this.rotateResizeCorner1.Angle = this.angle;
                this.rotateResizeCorner2.Angle = this.angle;
                this.rotateResizeCorner3.Angle = this.angle;
                this.rotateResizeCorner4.Angle = this.angle;
                this.rotateRotationSign.Angle = this.angle;
                this.RotateCornerPoints();
                this.SetConnectionLine();

                if (this.LoacationChanged != null) this.LoacationChanged(this, null);
            }
            if (this.isMoving)
            {
                //this.SetCornerPoints();
                this.SetResizeCorners();
                this.SetConnectionLine();
                this.SetRotationSign();
                if (this.LoacationChanged != null) this.LoacationChanged(this, null);
            }
            if (this.isResizing)
            {
                this.SetCornerPoints();
                this.SetResizeCorners();
                this.SetConnectionLine();
                this.SetRotationSign();
            }
        }
        else
        {
            // Make sure, the selection is removed
            this.EnsureSelectionRemoved();

            // Movement is disabled
            this.isMoving = false;
        }
    }
    else
    {
        // Hide the content container from the parent element
        if (this.contentContainer.Visibility != Visibility.Hidden) this.contentContainer.Visibility = Visibility.Hidden;

        // Make sure, the selection is removed
        this.EnsureSelectionRemoved();

        // Movement is disabled
        this.isMoving = false;
    }


}

我不太确定这是否是所有重要的代码。是的,我知道此代码还有其他问题。一旦我知道了定位问题的方向,我将予以纠正。

0 个答案:

没有答案